これを試しましたが、コードはコンパイルされませんでした。
class GenericClass<T>() {
private var arr : Array<T>? = null
{
arr = Array<T>(10, { null })
}
}
これを試しましたが、コードはコンパイルされませんでした。
class GenericClass<T>() {
private var arr : Array<T>? = null
{
arr = Array<T>(10, { null })
}
}
このコードには 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 の配列に型キャストします。コンパイラは警告を発行しますが、私たちの意志に従います。
上記の問題のある例が残っていることに注意してください。つまり、この方法で作成された配列を、文字列の配列が期待される場所に渡すと、実行時に失敗します。
方法
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?>