Странное поведение с подстановочными знаками Java, когда class is generic

Я думал, что хорошо разбираюсь в дженериках Java.

Этот код НЕ КОМПИЛИРУЕТСЯ ] и я знаю почему.

Мы можем передать методу тестирования только List типа Animal или его супертип (например, List of Objects)

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);
    }        
}

Но вот и странная часть (по крайней мере, для меня).

Если мы объявим класс Test как общий добавив только , тогда он СОБИРАЕТ ! и выбрасывает 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

Мой вопрос: почему добавление универсального типа класса (который нигде не используется) привело к компиляции класса и изменению поведения подстановочных знаков?

6
задан bary 16 May 2011 в 21:25
поделиться