Как создать общий массив, заполненный нулями в Kotlin?

Я пробовал это, и код не компилировался.

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

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

2 ответов


в этом коде есть две ошибки компилятора: одна - о типах с нулевым значением, а другая-о дженериках.

Nullable типы. Kotlin применяет дисциплину nullable references, и поскольку T может быть создан, скажем, со строкой, делающей arr типом Array, компилятор не позволяет вам помещать null в этот массив. Если вам нужны нули, вы должны изменить тип на Array:

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

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

дженериков. Пример выше все еще есть ошибка времени компиляции, потому что мы пытаемся построить массив неизвестного типа T. обратите внимание, что эта проблема существует и в Java. Котлин, компилируемый в байтовый код JVM, влечет за собой две вещи:

  • аргументы типа generics удаляются во время выполнения,
  • за исключением общих аргументов массивов.

это означает, что в байтовом коде Котлин должен создать массив некоторого конкретного типа, а не неизвестного типа T. Это может создавайте массивы объектов всякий раз, когда он видит массив, но это не сработает, например, в этом случае:

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

здесь, в последней строке, мы пытаемся передать объект[] , где ожидается строка [], и получить ошибку времени выполнения.

вот почему Котлин отказывается создавать массивы T. вы можете обойти эту проблему, явно подавляя систему типов, т. е. используя приведения типов:

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

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

здесь мы явно запрашиваем создание массива любого (скомпилированного Object []), а затем введите его в массив T. компилятор выдает предупреждение, но подчиняется нашей воле.

обратите внимание, что проблемный пример выше остается, т. е. если вы передадите массив, созданный таким образом, где ожидается массив строк, он потерпит неудачу во время выполнения.


метод

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

из 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?>