通過一個例子說明
新建一個動物基類 Animal
public class Animal { }
新建兩個子類(狗和貓)
public class Dog extends Animal { }
public class Cat extends Animal { }
新建一個動物類型(Animal)的的類集合(假設這個類集合實現了集合功能)
public class AnimalCollection<T extends Animal> { public void addAnimal(T t){} }
假設現在需要定義一個往動物類型集合(AnimalCollection)新增動物的方法,現在有兩種方式
1、使用泛型
public static <T extends Animal> void addAnimal(AnimalCollection<T> animalCollection){}
2、使用通配符
public static void addDog(AnimalCollection<? extends Dog> animalCollection){}
上面兩種方法都可以正常編譯運行的
如果上面兩個方法的參數不是動物類集合(AnimalCollection),而是Animal或其子類對象呢?
可以看到想要通過通配符來定義參數類型會編譯器會報錯的
所以可以這樣理解,泛型T是對方法的類型的一種“佔位”方式,而通配符?實際上只能對形如 AnimalCollection<T> 這樣的參數中T的替換以及對T指向的類型的範圍限制實現方式。泛型T是對方法的參數類型的佔位,在調用帶泛型的方法的時候,參數類型可以是T所限定範圍內的任何類型,而通配符?只能用於方法中形如 AnimalCollection<T>、ArrayList<T> 這樣的類型,注意AnimalCollection<T>實際上就是一種類型,而T並不是某一種具體的類型,T可以表示AnimalCollection<Animal>、ArraryList<Dog>這種類型,也可以表示Animal、Dog、Cat這樣的類型