私はJavaジェネリックについてある程度理解していると思いました。
このコードはコンパイルされません。理由はわかっています。
テストメソッドに合格できるのは、動物タイプのリストまたはそのスーパータイプ(オブジェクトのリストなど)のみです。
package scjp.examples.generics.wildcards;
import java.util.ArrayList;
import java.util.List;
class Animal {}
class Mammal extends Animal {}
class Dog extends Mammal {}
public class Test {
public void test(List<? super Animal> col) {
col.add(new Animal());
col.add(new Mammal());
col.add(new Dog());
}
public static void main(String[] args) {
List<Animal> animalList = new ArrayList<Animal>();
List<Mammal> mammalList = new ArrayList<Mammal>();
List<Dog> dogList = new ArrayList<Dog>();
new Test().test(animalList);
new Test().test(mammalList); // Error: The method test(List<? super Animal>) in the type Test is not applicable for the arguments (List<Mammal>)
new Test().test(dogList); // Error: The method test(List<? super Animal>) in the type Test is not applicable for the arguments (List<Dog>)
Dog dog = dogList.get(0);
}
}
しかし、ここに奇妙な部分があります(少なくとも私にとっては)。
<T>を追加するだけでクラスTestをジェネリックとして宣言すると、COMPILES!そしてjava.lang.ClassCastExceptionをスローします:
public class Test<T> {
...
}
、
Exception in thread "main" java.lang.ClassCastException: scjp.examples.generics.wildcards.Animal cannot be cast to scjp.examples.generics.wildcards.Dog
私の質問は、ジェネリッククラスタイプ<T>(どこでも使用されていない)を追加すると、クラスがコンパイルされ、ワイルドカードの動作が変更された理由です。