How to create a generic array filled with nulls in

2019-04-06 23:56发布

问题:

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

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

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

回答1:

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

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
    }
}

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:

  • generics type arguments are erased at runtime,
  • except for generic arguments of arrays.

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)
}

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

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?>
    }
}

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.



回答2:

method

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

from docs

/**
*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?>


标签: kotlin