I tried this, and the code didn't compile.

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

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

推荐答案

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

Nullable types.Kotlin强制执行可空引用的规则,并且由于T可能会被实例化,例如,字符串使arr成为数组类型,编译器不允许您将空值放入该array.如果需要空值,则必须将类型更改为数组:

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

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

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:

  • 泛型类型参数在运行时被删除,
  • except for generic arguments of arrays.

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

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

在这里,在最后一行中,我们试图传递对象[],其中字符串[]是预期的,并得到一个运行时错误.

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

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

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

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

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

Kotlin相关问答推荐

为什么Kotlin不用static inner class来实现带有object关键字的单例呢?

区分函数和扩展

如何在 Kotlin 中使用具有继承的泛型

如何从kotlin中的ArrayList中删除所有元素

禁用 Android 12 默认启动画面

如何解决此错误请Kotlin:[Internal Error] java.lang.ExceptionInInitializerError

带有迭代器函数的 Kotlin 无限序列

在 Kotlin 中实现 (/inherit/~extend) 注解

Jetpack Compose State:修改类属性

Kotlin 中的内联构造函数是什么?

Kotlin not nullable值可以为null吗?

Kotlin:子构造函数如何使用其父构造函数的辅助构造函数?

Kotlin 扩展函数 - 覆盖现有方法

Kotlin中具有多个参数的绑定适配器

如果作为 RxJava Observable 提供,Kotlin 密封类子类需要强制转换为基类

在 Kotlin 中创建非绑定服务

uses-sdk:minSdkVersion 16 不能小于库中声明的版本 23

在 kotlin 中,如何将主构造函数中的属性设置器设为私有?

Kotlin扩展函数与成员函数?

在多平台子元素中使用kapt