1. T通常用於類后面和 方法修飾符(返回值前面)后面 ,所以在使用之前必須確定類型,即新建實例時要制定具體類型, 而?通配符通常用於變量 ,在使用時給定即可
? extends A : 通配符上界 通常用於參數,來界定傳入的參數上界,不能對參數進行變更,因為無法確定參數的具體類型。
public class A{
public void act(List<? extends Animal> list) {
for (Animal animal : list) {
animal.eat();
}
}
}
public class ATest{
public static void main(String[] args) {
A a= new A();
//Test 1
List<Animal> animalList = new ArrayList<>();
animalList.add(new Cat("cat1"));
animalList.add(new Bird("bird1"));
a.act(animalList); //可以通過編譯
//Test 2
List<Cat> catList = new ArrayList<>();
catList.add(new Cat("cat2"));
catList.add(new Cat("cat3"));
a.act(catList); //也可以通過編譯
}
}
對act 方法 傳遞 任何 繼承Animal 的list 對象都是可以的。
但也正是 因為參數具體類型的不確定,所以無法對改參數進行更新操作,如add元素, 如add(cat),單數參數 可能是 List<dog>,List<cat>,List<animal> ,雖然第2,3 種是可以執行add(cat) 的,但是第1中是無法執行的,由於這種
不確定性,為了安全,java 禁止向該參數添加任何對象,除了null.
? supper B 通配符上界,不僅可以傳遞任何B及其父類。還可以對參數進行添加 B 及其子類,原因: 該參數可能是B,B父類, 由於子類可以指向父類,那么就是說我對參數添加一個B或者B的子類是可行的,就如List<B> l = new ArrayList<>(); l.add(B);l.add(Bchild),是正確的。
// 可以正確執行, 其效果就如2
public void testAdd(List<? super Bird> list){
list.add(new Bird("bird"));
list.add(new Magpie("magpie")); //Magpie 是Bird 的子類
}
//2 可以執行
List<? super Bird> list = new ArrayList<>();
list.add(new Bird("bird"));
list.add(new Magpie("magpie"));
list.add(new Animal("animal"));
