ジェネリックス(総称型)の使い方が混乱したのでよく使う例を書いてみました。
クラスの引数として決めるたい
public class Foo<T> {
T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
複数をパラメータを利用するときはFoo<T, U>
とカンマで区切っておけばいいです。
サブクラスを強制しておきたい
public class Foo<T extends Parent> {
T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
あるメソッドを使うときだけ
クラス全体で指定しておくと一時的に決めたいときに不便です。
例えば、Listを配列に変換したいときに
List list = new ArrayList<String>();
list.add("foo1");
list.add("foo2");
list.add("foo3");
String[] strList = list.toArray(new String[list.size()]);
のようにtoArrayメソッドを使うことがあると思います。このときの実装は
public class Foo {
public <T> T get(T t) {
return t;
}
}
このとき引数の型を見てTが決定されます。
※話はそれますが、java8以降ラムダ式が導入され、List(Collection)がとても使いやすくなったので配列に変換する実装にしないほうがよさそうです。
インスタンスは生成できない
当然といえば当然ですが、new T()
なることはできません。理由はTが何者であるかわからない以上、インスタンスが生成できる保証がないからでしょう。
public class Foo<T extends Parent> {
public T get() {
return new T(); // できない!!
}
}
new T()
するようなコーディングを実現するにはjavaリファクタリングを利用してClassクラスからインスタンスを生成するとできるみたいですが、パフォーマンスが非常に落ちるようです。