web-dev-qa-db-ja.com

タイプ消去されたリストをKotlinの配列に変換する方法は?

関数toArrayは、型消去されたリストをT、つまりArray<String>今。

inline fun <reified T> toArray(list: List<*>): T {
    return list.toTypedArray() as T
}

toArray<Array<String>>(listOf("a", "b", "c")) // should be arrayOf("a", "b", "c")

ただし、toArrayはこのエラーをスローします。

Java.lang.ClassCastException:[Ljava.lang.Object; [Ljava.lang.String;にキャストできません。

あなたはなにか考えはありますか?

15
mmorihiro

ここでの問題は、実際にObject[]String[]にJavaでキャストしようとしていること、またはArray<Any>Array<String>にキャストしようとしていることですが、これは異なるオブジェクトです。

したがって、このステートメント:

list.toTypedArray()

Array<Any?>を返し、それをArray<String>にキャストしてClassCastExceptionを取得しようとします。

直し方?

型パラメーター自体を渡し、Listをキャストすることをお勧めします。

inline fun <reified T> toArray(list: List<*>): Array<T> {
    return (list as List<T>).toTypedArray()
}

toArray<String>(listOf("1", "2"))
41
Ruslan
  1. 型付きリスト(例:List<*>)ではなく、Array<String>を型付き配列(例:List<String>)に変換する必要性に挑戦することをお勧めします。

    後者はKotlinで非常にうまく行うことができます。

    list.map { it as String }
    

    Kotlinのリスト型と配列型の違い および Javaプラクティス->古いクラスよりもコレクションを優先 を読むことをお勧めします。

  2. それでも配列を操作する必要があると感じる場合は、Kotlinのさまざまな「マップ」関数に似た「マップ」関数を作成することをお勧めします。

    inline fun <T, reified R> List<T>.mapToTypedArray(transform: (T) -> R): Array<R> {
        return when (this) {
            is RandomAccess -> Array(size) { index -> transform(this[index]) }
            else -> with(iterator()) { Array(size) { transform(next()) } }
        }
    }
    

    その後、List<*>を型付き配列に効率的に変換できます。

    list.mapToTypedArray { it as String }
    
4
mfulton26

何らかの理由で、これを実行しようとしたときに無効な引数番号の例外が発生していました:

val argumentTypeMirrors = mutableListOf<TypeMirror>()
... // add items to argumentTypeMirrors
val array = argumentTypeMirrors.toTypedArray()

そして、私はそれをこのようにしてやった:

val argumentTypeMirrors = mutableListOf<TypeMirror>()
... // add items to argumentTypeMirrors
val array = Array(argumentTypeMirrors.size) {
    argumentTypeMirrors[it]
}

その後、arrayパラメータとして渡すために、*arrayvarargsを破棄することができました。

0
epool