java:(String [])List.toArray()はClassCastExceptionを出します


107

次のコード(Androidで実行)では、常に3行目にClassCastExceptionが表示されます。

final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();

これは、v2がObject [0]の場合、およびその中に文字列がある場合にも発生します。何かアイデアは?


-あなたは共変性と反変性について読むことをお勧めしますen.wikipedia.org/wiki/...
Hut8

Tがインスタンス化のファクトリメソッドとのインターフェイスである場合はどうでしょうか。
sebaj 2011

2
@LaceCard-これは、共分散/反変に非常に間接的にのみ関連しています。実際の問題は、これがtoArray()メソッドの指定された動作の直接的な結果であるということです。
スティーブンC

回答:


249

これは、

 toArray() 

Object []を返します。これはString []にキャストできません(コンテンツがStringであっても)これは、toArrayメソッドが取得するのは

List 

ではなく

List<String>

ジェネリックスはソースコードのみのものであり、実行時には使用できないため、作成する配列のタイプを決定できません。

使用する

toArray(new String[v2.size()]);

適切な種類の配列(String []と適切なサイズ)を割り当てる


3
cuzジェネリック、それが理由です
Kaleb Brasee

2
@Kaleb-真実ではない。または、少なくともそれが本来の理由ではありません。toArrayコレクションクラスの前に存在していた方法は、一般的なでした。
スティーブンC

10
これは正しい解決策ですが、正しい説明ではありません。Object []をDouble []に​​キャストすることはできません。これは言語機能であるため、それ以上のものはありません。Genericsとは関係ありません。本当にDoubleであると想定して、ObjectをDoubleにキャストできます。論理的には、配列でも同じことができますが、それは単に言語の一部ではありません。ObjectをDoubleにキャストすると、Objectが実際にDoubleであることを確認するランタイムチェックが行われます。DoubleをObjectにキャストする場合、ObjectはDoubleの継承階層にあるため、ランタイムチェックはありません。
KyleM 2013年

5
IntelliJでこれを行うと、次の警告が表示されますtoArray(new String[0])。「適切なサイズの配列を作成するために必要なリフレクション呼び出しが非常に遅いため、プリサイズ配列を使用する古いJavaバージョンでは推奨されました。ただし、OpenJDKの最新のアップデート以降6この呼び出しは本質的なものであり、空の配列バージョンのパフォーマンスを同じにし、場合によってはさらに向上させました。また、sizetoArray呼び出しの間で競合が発生する可能性があるため、事前にサイズ設定された配列を渡すことは、同時コレクションにとって危険です。
Mikepote

35

あなたは間違って使用しています toArray()

Javaのジェネリックスは主に構文上の砂糖であることを思い出してください。ArrayListは、そのすべての要素が文字列であることを実際には認識していません。

問題を解決するには、に電話してくださいtoArray(T[])。あなたの場合、

String[] v3 = v2.toArray(new String[v2.size()]);

総称形式toArray(T[])はを返すT[]ため、結果を明示的にキャストする必要はありません。


1
String[] v3 = v2.toArray(new String[0]); 

トリックも行います。正しいArrayTypeがメソッドに渡されれば、キャストする必要もなくなることに注意してください。


0
String[] str = new String[list.size()];
str = (String[]) list.toArray(str);

このように使います。


1
お願いします!コードをフォーマットしてください!「ctrl + k」を押してすべてを選択するか、コードの最初の文字の前と最後の文字の間に「 `」を追加します。回答を作成するときに、上部のヘルプで「{}」を選択することもできます。
MK
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.