パラメータで受け取った型のインスタンスを生成
C++のTemplateとJavaのGenericsを比べるとき、
- パラメータで受け取った型のインスタンスを生成できない
という話が出てくることがある。
import java.util.Vector; class Elem { } public class Test { // しかるべき方法で初期化された、要素数nのVector<T>がほしい static <T> Vector<T> make_n_vector(int n) { Vector<T> result = new Vector<T>(); while (n > 0) { T elem = new T(); // コンパイルエラー result.add(elem); n--; } return result; } public static void main(String[] args) { Vector<Elem> v = make_n_vector(10); } }
これがうまくいかない原因は、型パラメータTはコンパイルされた後で消えてしまうため、どのクラスをnewすればいいか分からなくなるという点につきる。
逆に言うと、コンパイルされた後でも消えない方法で型についての情報を渡すだけでうまくいく。
import java.util.Vector; class Elem { } public class Test2 { static <T> Vector<T> make_n_vector(Class<T> elem_class, int n) { Vector<T> result = new Vector<T>(); while (n > 0) { try { T elem = elem_class.newInstance(); // これならOK result.add(elem); } catch (IllegalAccessException iae) { // ここと } catch (InstantiationException ie) { // ここに失敗したときの処理 // この例なら RuntimeException とか AssertionError を投げるのがいいかな? } n--; } return result; } public static void main(String[] args) { // 呼び出し側で、型パラメータの代わりにクラスリテラルを渡す Vector<Elem> v = make_n_vector(Elem.class, 10); } }