quabbinの日記: Genericsとjava.util.Collection#toArray()
JavaのGenericsは面白いが、ちょっと凝ったことをすると実装に戸惑う。
たとえばjava.util.Collectionの#toArray()。
実際のJDKではtoArrayは
Object[] toArray();
として実装されている。
Collectionインターフェースは
interface Collection
と宣言されているので、toArrayはGenericで指定されている型変数Eに対して
E[] toArray();
として欲しいものだろう。
実際調べてみると、そのような間違いをしているblogを見かけたりもした。
引数を取る
Object[] toArray(Object[] a); // J2SE 1.4
のほうは、
T[] toArray(T[] a); // J2SE 5.0
となり、String[] array = list.toArray(new String[list.size()]);のような実装ができるにもかかわらず。
なぜそのようなAPIが用意されていないのだろう。
実際のところ論議を読んでいないのでわからないが、多分にこの現象は考慮済みであろう。
#toArray()は#toArray(T[])に対し、引数をもたないために自分でArrayを作成せねばならない。
まず仕様として、#toArrayは返却する配列のComponentTypeを取得する手段として、どうしてもclass宣言の場所にある型変数Eを使わねばならないが、これは引数の型を正とするべく実装が素直であろう#toArray(T[])と、同じ名前なのに振る舞いが変わってしまい、美しくないと結論付けたのではないだろうか。
次に実装上として、多分に型変数Eに対してEのClassオブジェクトを取得するAPIがないこと問題となろう。なぜそういうAPIなり構文なりを用意しなかったかは別の問題として。
よって、#toArray()は文脈上はキャスト不要としてほしいのに、キャスト不要とならずに戸惑うこととなる。
どうしてあげればいいのだろうか…。
Genericsとjava.util.Collection#toArray() More ログイン