傳遞一個類型對象到泛型類型所引發的問題


 

 

1 class People{};
2 class Student extends People{};
3 class teacher extends People{};
4 //創建一個List,目的是將它用來存儲所有繼承自People基類的對象實例,但實際上我們無事可做!
5 List<? extends People> list = new ArrayList<Student>();    
6 //list.add(new Student());    //compile error
7 //list.add(new People());        //compile error
8 //list.add(new Object());        //compile error

從上面可以看出,無論我們是add一個基類實例還是派生類實例到list中都會發生編譯錯誤,這是為什么呢?
我們看下面這個例子:
print(list.indexof(new Fruit())); //ok! return -1, the argument is Object
 
對比一下,我們發現add()接受一個具有泛型參數類型的參數,但是indexof將接受Object類型的參數。當我們創建一個List<? extends People>時,addd的參數也同步變成了<? extends People>.但是從這樣的描述中,編譯器並不能了解到這里到底需要People的哪個具體子類型,因此它不會接受任何類型的Fruit,甚至是Object類型。---因此,編譯器直接拒絕 對參數列表中設計通配符的方法(比如:add())的調用. 
 

這就是這個compile eror的原因!
 
那么怎么解決這個問題呢? 我們可以使用超類型通配符,通過調用方法指定<? super Myclass>,甚至使用類型參數<? super T>,這樣就可以安全的傳遞一個類型對象到泛型類型中了,這在java中稱之為 “逆變”,

 1 static <T> void method1(List<? super T> list, T item){
 2         list.add(item);
 3 }
 4 static void test1(){
 5 List<Fruit> list = new ArrayList<Object>();
 6         method1(list, new Apple());
 7         method1(list, new Orange());
 8         list.add(new Blanla());    //一般用法
 9       for (Fruit fruit : list) {
10             println(fruit.getClass().toString());
11         }
12 }
13     
14 Output:
15 class demo5.Apple
16 class demo5.Orange
17 class demo5.Blanla                

 <? super Fruit>表示list所持有的類型為Fruit與Fruit的基類中的某一類型,以上面這個例子為例,Apple和Orange必定是這某一類型的子類,所以add方法能正確的被調用,從上面可以看出,extends定義了泛型的上界,而super確定了泛型的下界。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM