20

Java ジェネリック以前Collection.toArray()は、開発者が期待する配列の型を知る方法がありませんでした (特に空のコレクションの場合)。私が理解しているように、これがイディオムの背後にある主な理論的根拠でしたcollection.toArray(new E[0])

ジェネリックを使用するとCollection<E>.toArray()、インスタンスEおよび/またはその特殊化でいっぱいの配列のみを返すことができます。Object[]戻り値の型がまだ asではなくas であるのはなぜだろうかE[]E[]私の意見では、代わりにを返すことは、Object[]既存のコードを壊すべきではありません。

参照:Collection.toArray()およびCollection.toArray(T[])関連トピックjava: (String[])List.toArray() は ClassCastException を与える

4

3 に答える 3

9

とても良い質問です。答えは、ジェネリックは「消去」とも呼ばれるということです。それは単なる名前ではありません。ジェネリックによってコーディングされた情報は、コンパイル時にのみ使用され、その後削除されます。したがって、JVM はこのジェネリック型Eを認識していないため、配列を作成できませんE[]

他のメソッドtoArray(T[] a)は、実行時に引数から型に関する情報を受け取ります。これが、このメソッドのプロトタイプが<T> T[] toArray(T[] a): 型 T の配列を取得し、型 T の配列を返すことができる理由です。型はパラメーターとして渡されます。

于 2011-05-30T07:44:32.033 に答える
5

「タイプ消去」は部分的な説明にすぎませんCollection。 もそのメソッドも、実行時toArray()の情報を持っていません。E

また、下位互換性のため、 をCollection.toArray()返す必要がありObject[]ます。Java 1.5 より前は、コレクションのジェネリック型を知る方法がなかったため、これが唯一の妥当な API 設計でした。

于 2011-05-30T07:46:59.600 に答える
1

@Lukas、「new E[]」に関して</p>

ご想像のとおり、新しい E[0] によってコミラー エラーが発生しました。私が見つけた回避策は次のとおりです。

final E[] returnArray = (E[]) events.toArray( new Event[ events.size() ] );

NB コードはテンプレート クラス Listener<E extends Event> にあります。

私の回避策では、型消去が問題と解決策の両方です。(E[]) へのキャストは、その正確な型が Event[] に消去されるため安全です。私が目にする唯一の欠点は、「チェックされていない操作または安全でない操作」に関するコンパイラの警告です (これは明らかに、この場合、型消去が与えられた場合のキャストではありません)。

@Lukas、下位互換性について

下位互換性に大きな問題はないと思います。戻り値の型をより特殊にすることは、引数の型をより特殊にすることと同じではありません。

言い換えれば、これまで Collection.toArray() が Object[] を返すことを期待していたソース コードは、代わりに E[] を受け取って完全に満足するはずです。

また、バイトコードに関しては、Object[] と E[] は型消去のためにとにかく同じです。

于 2011-05-30T14:40:41.963 に答える