いいえ、ありません。コンパイラはどの型を返すかをどのように知るのでしょうか? コンストラクター内の ArrayList のジェネリック型は、コンパイル時には認識されません。クラス全体をジェネリックにするか、別のアプローチを取る必要があります。
このことを考慮:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(arrList);
String testStr = test.returnWhat();
System.out.println("testStr");
}
private final List myList; //warning
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat() {
return (T) myList.get(0); //warning
}
}
これは機能しますが、マークされた行に警告が表示されます。したがって、クラス全体をジェネリックにすることなく、説明していることを達成する方法は実際にはありません。なぜなら、次の場合:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(); // now what?
String testStr = test.returnWhat(0); // no warning...
JPanel p = test.returnWhat(0); // goes through without warning, real nice...
test.returnWhat(0); // returns Object
Test test2 = new Test(arrList);
test2.addElement(new Object()); // boom, inserted object into list of string.
String nono = test2.returnWhat(1); // the universe goes down. assign an object to string without warning. even
// though one COULD think the class is generic.
}
// private List<T> myList = new ArrayList<T>(); compiler error, T is unknown
private List myList = new ArrayList();
public Test() {
myList.add(new Object());
}
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat(int index) {
return (T) myList.get(index);
}
public <T> void addElement(T el) {
myList.add(el);
}
}
2 番目のものは、myList がジェネリックになるとコンパイルされません。デフォルトのコンストラクターが使用されている場合、コンパイラーはどのようにして <T> の型を判別できますか?
さらに、これにより、特定のタイプのみが挿入されるという事実に依存するコレクション内のオブジェクトで深刻な問題が発生する可能性があります。
これにより、次の例外が生成されます。
Exception in thread "main" java.lang.ClassCastException:
java.lang.Object cannot be cast to java.lang.String at
Test.main(Test.java:27)
私はあなたを納得させることができましたか?
本当にいい質問ですね。私はこれについてかなり考えなければなりませんでした。