Javaのジェネリクスの注意点

JavaだとList型などで利用されるジェネリクスですが、元々の言語仕様の関係でちょっとややこしいことになってます。

1.オーバーロードできない

たとえば、List<Integer>型についてはその値の合計の文字列を、List<String>型については文字列の合算を算出する機能を実装しようとしたときに、以下のようにオーバーロードを用いることはできません。

public String getSumString(List<String> elements) {
  // hogehoge
}
public String getSumString(List<Integer> elements) {
  // fugafuga
}

これは、ジェネリクスの持つ型情報がコンパイル時にのみ存在し、実行時には消滅している(そのため上記2つのメソッドを区別できず、オーバーロードによって解決できない)という問題に起因しています。

2.共変・反変に対応していない

Javaのジェネリクスは全てが非変です。従って、以下の様なコードを書くことはできません。

ArrayList<CharSequence> list = new ArrayList<String>();

ただし、以下のように個別の代入において子クラスを用いることは可能です。

ArrayList<CharSequence> list = new ArrayList<CharSequence>();
list.add("foo");

この他にもいくつか問題があるようですが、詳しくは参考ページなどを参照してください。

参考