読者です 読者をやめる 読者になる 読者になる

今更ながらのGenericsその1

JDK5から追加された機能のGenerics。今じゃもう当たり前のように使われているし、みんな便利だと思ってる。ところが実際にそのGenericsの機構を踏まえた上でAPIを提供する側-フレームワークの作成者など-の立場に立ってみると途端にその難しさに地味に悩んでしまう。そんな訳でもう少し深く理解する為にも1から少しずつ勉強しなおして行こうかなと。

そんな訳で基本。恐らく一番分かりやすいと思われるListの例。

//5以前はこう
List list = new ArrayList();
list.add("1");
String s = (String)list.get(1); 

//5からはこう書ける
List<String> list = new ArrayList<String>();
list.add("1");
String s = list.get(1); 

と、まぁcastする必要がなくなる。としているところでListに何を入れられるかを書いていてListの中身が何かをコンパイラが分かってるわけだねー。だから逆にこういうことも出来なくなる。

List<String> list = new ArrayList<String>();
list.add(new Integer(1));//ここでコンパイルエラー

まぁ、単純Stringの入れ物として宣言してるのでInteger*1は入らない。簡単なところだとこの辺から使えるし一番恩恵が分かりやすいポイントでもある。

次、クラス、メソッドに対してのGenerics

public class Beans<T> {

 private List<T> beans = new ArrayList<T>();

 public void add(final T bean) {
  beans.add(bean);
 }

 public T get(final int index) {
  return beans.get(index);
 }

}

Generics便利だなーとか思って使い出して一番最初にぶちあたる謎文法?がこれ。Tってなんだろう・・・ってなるねまず。こいつは<>を指定する時につかうObject型みたいなものとして覚えてる。このクラスをnewする時に指定した型によってTのところが全て置き換わる感じになる。まぁ、百聞は一見にしかず。

//Productはid、name、priceをfieldにもってると考えてちょ
Beans<Product> products = new Beans<Product>();
products.add(new Product(1, "ガム", 100));
products.add(new Product(2, "iPod", 39800));
products.add(new Product(3, "ビール", 320));
Product p1 = products.get(0);
Product p2 = products.get(1);
Product p3 = products.get(2);

まぁ、こんな感じでかけるようになる。Beansとしてnewした場合はBookしか入れられないようにもできる。caastもいらなくなるし間違って変なObjectを突っ込むこともなくなるし良いことづくめ。ただでもこれだけだとあまり利点がー!利点がー!という感じなので次回はも少し突っ込んだものを見ていこうかなと思いますん。

*1:後輩用だったりもするのでひとまずboxingはすっ飛ばす