ごきげんうるわしゅぅ。
さて、今回はジェネリックスの話題。
ジェネリックスになれてくるとうっかり書いてしまうのが、以下のコード。
public class MyArray<E>{ private E[] elements; public MyArray(int n){ elements = new E[n]; } public E get(int index){ return elements[index]; } public void set(int index, E value){ elements[index] = value; } }
これは機能しそうですが、実際には以下でコンパイルエラーになります。
elements = new E[n];
え?なぜできないの?って考えてしまうのですが、Eなどの具象化不可能型*1は配列を生成できないのです。
回避方法その1
えぇい、List
List<E> elements;
回避方法その2
まさに、ArrayListのソースコードにあったwww JDKのソース読んでてよかたーwww
ArrayListクラスの中
* Arrayだけに内部は固定長の配列です。
余談ですが、ArrayList<E>のE型ではなくObjectで管理されるんですね。
何気なく言及しているのですが、これがずばり回避方法。そもそもEの配列でなくObjectの配列で管理し、外部とのやり取りにはEを使う方法。(本を買う余裕がなくてもJDKのソースを読めばよいわけですね。なるほどー)
ArrayList
private transient Object[] elementData;
当然追加する際は難なく追加可能。
public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
要素を取得する場合はE型でキャストして返す。
public E get(int index) { RangeCheck(index); return (E) elementData[index]; }
ジェネリック型配列は作れないが、上記の回避方法で要件を満たすことができるかもしれない。
*1:実行時の表現がコンパイル時より少ない表現の型