且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-11-18 20:55:16

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

There are two compiler errors reported in this code: one is about nullable types and another about generics.

可空类型. Kotlin强制执行可空引用的规则,并且由于T可以用String实例化,使arr的类型为Array,因此编译器不允许您将null放入此数组中.如果要为空,则必须将类型更改为Array:

Nullable types. Kotlin enforces a discipline of nullable references, and since T may be instantiated with, say, String making arr be of type Array, the compiler does not allow you to put nulls into this array. If you want nulls, you have to change the type to Array:

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

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

泛型.上面的示例仍然存在编译时错误,因为我们正在尝试构造未知类型T的数组.请注意,Java中也存在此问题.将Kotlin编译为JVM字节码需要两件事:

Generics. The example above still has a compile-time error, because we are trying to construct an array of an unknown type T. Note that this problem exists in Java as well. Kotlin being compiled to JVM byte code entails two things:

  • 泛型类型参数在运行时被删除
  • 数组的通用参数除外.

这意味着Kotlin必须在字节码中创建一个特定类型的数组,而不是未知类型T.它可以在看到Array时创建Objects的数组,但是在这种情况下将不起作用.情况:

This means that in the byte code Kotlin has to create an array of some concrete type, and not an unknown type T. It could create arrays of Objects whenever it sees Array, but this would not work, for example, in this case:

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

在这里,在最后一行中,我们尝试传递Object []到需要String []的地方,并获得运行时错误.

Here, in the last line, we are trying to pass Object[] where String[] is expected, and get a runtime error.

这就是为什么Kotlin拒绝创建T的数组.您可以通过显式禁止类型系统(即通过使用类型强制转换)来解决此问题:

This is why Kotlin refuses to create arrays of T. You can work around this problem by explicitly suppressing the type system, i.e. by using type casts:

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

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

在这里,我们明确要求创建Any数组(编译为Object []),然后将其类型转换为T数组.编译器会发出警告,但要遵守我们的意愿.

Here we explicitly request creation of an array of Any (compiled to Object[]), and then type-cast it to an array of T. The compiler issues a warning, but obeys our will.

请注意,上面仍然有问题的示例仍然存在,即,如果将这样创建的数组传递给期望的字符串数组,那么它将在运行时失败.

Note that the problematic example above remains, i.e. if you pass the array created this way where an array of strings is expected, it ill fail at run time.