12

これを試しましたが、コードはコンパイルされませんでした。

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

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

4 に答える 4

19

このコードには 2 つのコンパイラ エラーが報告されています。1 つは null 許容型に関するもので、もう 1 つはジェネリックに関するものです。

Null 許容型。Kotlin では、null 許容参照の規律が適用されます。T は、たとえば、arr を Array 型にする String でインスタンス化される可能性があるため、コンパイラは、この配列に null を入れることを許可しません。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 バイトコードにコンパイルされる Kotlin には、次の 2 つのことが伴います。

  • ジェネリック型引数は実行時に消去されます。
  • 配列のジェネリック引数を除く。

これは、バイト コードで、Kotlin が不明な型 T ではなく、具体的な型の配列を作成する必要があることを意味します。配列が検出されるたびにオブジェクトの配列を作成できますが、これは機能しません。たとえば、この場合は次のようになります。

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

ここでは、最後の行で、String[] が予期される場所に Object[] を渡そうとしていますが、実行時エラーが発生します。

これが、Kotlin が T の配列の作成を拒否する理由です。型システムを明示的に抑制すること、つまり型キャストを使用することで、この問題を回避できます。

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

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

ここでは、(Object[] にコンパイルされた) Any の配列の作成を明示的に要求し、それを T の配列に型キャストします。コンパイラは警告を発行しますが、私たちの意志に従います。

上記の問題のある例が残っていることに注意してください。つまり、この方法で作成された配列を、文字列の配列が期待される場所に渡すと、実行時に失敗します。

于 2013-11-30T06:40:48.980 に答える
2

方法

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?>
于 2016-07-31T18:57:48.440 に答える