当前位置: 首页 > 知识库问答 >
问题:

如何在Kotlin中创建一个填充Null的通用数组?

谭云瀚
2023-03-14

我尝试了这个,但代码没有编译。

class GenericClass<T>() {
    private var arr : Array<T>? = null

    {
        arr = Array<T>(10, { null })
    }
}

共有3个答案

楚瑞
2023-03-14

如果需要在构造函数中初始化数组,可以添加一个内联工厂方法,并使用具体化的T对其进行参数化。此解决方案的灵感来自答案https://stackoverflow.com/a/41946516/13044086

class GenericClass<T> protected constructor(
    private val arr : Array<T?>
) {
    companion object {
        inline fun <reified T>create(size: Int) = GenericClass<T>(arrayOfNulls(size))
    }
}

fun main() {
    val strs = GenericClass.create<String>(10)
    ...
}

请注意,构造函数受到保护,因为内联函数无法访问私有构造函数。

如果在创建对象后需要创建数组,可以将创建数组的lambda传递到方法中。Lambda可以在扩展函数内部创建,因此保留有关数组类型的信息。@PublishedApi注释用于封装私有方法填充

import GenericClass.Companion.fill

class GenericClass<T> {
    private var arr : Array<T?>? = null

    fun show() {
        print(arr?.contentToString())
    }

    private fun fill(arrayFactory: (size: Int) -> Array<T?>) {
        this.arr = arrayFactory(10)
    }

    @PublishedApi
    internal fun `access$fill`(arrayFactory: (size: Int) -> Array<T?>) = fill(arrayFactory)

    companion object {
        inline fun <reified T>GenericClass<T>.fill() {
            `access$fill`(arrayFactory = { size -> arrayOfNulls(size) })
        }
    }
}

fun main() {
    val strs = GenericClass<String>()
    strs.fill()
    strs.show()
}
吕承望
2023-03-14

方法

val array : Array<T?> = kotlin.arrayOfNulls<T>(size)

来自文档

/**
*Returns an array of objects of the given type with the given [size],
*initialized with null values.
*/
public fun <reified @PureReifiable T> arrayOfNulls(size: Int): Array<T?>
锺离晗昱
2023-03-14

此代码中报告了两个编译器错误:一个是关于可空类型,另一个是关于泛型。

可为空的类型。Kotlin强制执行可空引用的规则,并且由于T可以用字符串实例化,例如,使arr为Array类型,编译器不允许您将Null放入该数组。如果需要Null,则必须将类型更改为Array:

class GenericClass<T>() {
    private var arr : Array<T?>? = null

    {
        arr = Array(10, { null }) // No need to specify type arguments again
    }
}

泛型。上面的例子仍然有编译时错误,因为我们试图构造一个未知类型的数组。请注意,这个问题也存在于Java中。编译为JVM字节码的静态编程语言需要两件事:

  • 泛型类型参数在运行时被擦除,
  • 数组的通用参数除外。

这意味着在字节码中,Kotlin必须创建某种具体类型的数组,而不是未知类型的T。它可以在看到数组时创建对象数组,但这不起作用,例如,在这种情况下:

fun test() {
    fun foo(srts: Array<String?>) {
        // ...
    }
    val gc = GenericClass<String>()
    foo(gc.arr)
}

在这里,在最后一行中,我们尝试在需要字符串[]的地方传递对象[],并获得一个运行时错误。

这就是Kotlin拒绝创建T数组的原因。您可以通过显式抑制类型系统来解决此问题,即通过使用类型转换:

class GenericClass<T>() {
    val arr : Array<T?>

    {
        arr = Array<Any?>(10, { null }) as Array<T?>
    }
}

这里,我们显式请求创建一个Any数组(编译为Object[]),然后将其类型转换为T数组。编译器发出警告,但遵从我们的意愿。

请注意,上面的问题示例仍然存在,即如果您将以这种方式创建的数组传递给预期的字符串数组,那么它将在运行时失败。

 类似资料:
  • 问题内容: 我在Pandas DataFrame中有一列具有连续数字的列。 我想将所有这些值更改为一个简单的字符串,例如“ foo”,导致 问题答案: 只需选择该列并像往常一样分配: 分配标量值会将所有行设置为相同的标量值

  • 问题内容: 我设法根据矩阵内的一个指定数组(即数组内的数组)生成了一系列列表项。 我希望能够将一个变量(表示一个数组)传递给一个函数,以便它可以根据传递到其中的数组吐出一个无序列表,其中填充了列表项。 问题: 该函数一次只能使用一个数组 它还会在标记中产生逗号(大概是因为它将数组转换为字符串) 解决方案需要: 假设DOM中不存在无序列表 能够接受传递到它的不同阵列(,等) 生成没有逗号的列表项 J

  • 假设我有一个整数数组,如和一个简单的字符串,如。我如何循环通过数组和填充每一个值。假设是这样的: 输出: 到目前为止,我已经尝试了以下内容: 但是,它在print语句中给出了。解决这个问题最好的方法是什么?

  • 问题内容: 在Java中,如何创建在构建时填充的最终Set?我想做以下事情: 但是我不知道Java的正确语法。 问题答案: 试试这个成语:

  • 问题内容: 我知道该怎么做,但是我发誓您可以像[[0] = {0,0,0,0};那样填写;你是怎么做到的?我确实尝试过Google,但没有任何帮助。 问题答案: 您也可以将其作为声明的一部分:

  • 我需要创建PDF表格,可以用来从用户的输入。它们需要包含下拉框和文本框。请建议哪种软件或工具最适合我的目的