Generics

JDK 5.0でなされた言語仕様の拡張で、代表的なものがGenericsと呼ばれる機能です。 GenericsはC++でTemplateと呼ばれる機能のようなものです。といってもC++を知らない人には説明になっていませんね。C++のTemplateというのはGenericsのような機能で...怒られそうなのでやめますが、クラスを作成する際に別のクラスを参照して定義する場合に、その参照するクラスを特定しないでパラメータとして扱う、ということになりましょうか(返って解り難い説明になってしまいましたが)。

例を見たほうが話が早いでしょう。例えばjava.util.Listを考えてみましょう。1.4までの機能ではListの要素のオブジェクトは、全てのクラスのスーパークラスであるjava.lang.Objectのインスタンスになっています(Collectionは皆そうですね)。普通はListの要素に異なるクラスのインスタンスをまぜこぜに入れるような事はしませんが、やれなくは無いわけです。例えば、

	List list = new ArrayList();
	list.add(new Integer(1234));
	list.add("ほげほげ");
	list.add(new HashMap());
なんてなことも可能なわけですが、逆にStringだけを要素に持つListを作ったとしても、Objectとして取り出す口しかないので、、
	String value = (String) list.get(i);
のように、要素に応じてキャストしてやらなければなりませんし、もし要素がStringじゃ無いものが混じっていたりするとjava.lang.ClassCastExceptionがthrowされてしまいます。

このObjectを要素とする自由度は便利ではあるのですが、同時に危険でもあり、不便な事(キャストしないといけないとか)でもあるので、もう少し型付けされた(typed)Listが欲しいなあ、という話になったわけです。しかしString用のList、Integer用のList、JPanel用のListなんてのを別々に用意するのは余りにも馬鹿らしい(それくらいならObjectのListがあれば良い)というので、要素に入れるインスタンスのクラスそのものをパラメータ化してやろう、というのがGenericsというわけです。

Stringだけを入れるListが欲しければ、

	List<String> stringList = new ArrayList<String>();
と、Integerだけを入れるListが欲しければ、
	List<Integer> intList = new ArrayList<Integer>();
とすれば良いのです。List<String>までがクラス名みたいなものだと思ってください。要素を取り出す時も、
	String stringValue = stringList.get(i);
	Integer intValue = intList.get(i);
てな具合に、キャストがいりません。要素のクラスが決まってくるからです。

ArrayListの定義も、前は、

public class ArrayList extends AbstractList
	implements List, RandomAccess, Cloneable, java.io.Serializable
だったのが、5.0からは
public class ArrayList<E> extends AbstractList<E>
	implements List<E>, RandomAccess, Cloneable, java.io.Serializable
に変わっています。この<E>のEはEという名前のクラスではなく、ArrayList定義時には不明だけど、使うときに具体的にクラス名を指定してね、という意味(と言って良いか?)です。

Genericsの機能と、別途説明するforループの省略記法によって、Javaのソースコードはこれまでとは様変わりするものと思います。


JDK5.0  人材開発室 PoisonSoft