java 泛型(一)


我們在學習java的繼承規則時,已經知道任何需要父類型的地方,都可以被替換成子類型,現在我們有如下類的繼承結構:

[html] view plain copy
  1. // 子類Student可以轉換成父類Person  
  2. Student student = new Student();  
  3. Person person = student;  

然而泛型機制規定如下的轉換是錯誤的:

[html] view plain copy
  1. // Erro: Type mismatch: cannot convert from Result<Student> to Result<Person>  
  2. Result<Studentre_student = new Result<Student>(new Student(), new Student());  
  3. Result<Personre_person = re_student;  

在泛型機制里無論S和T這兩個類是什么關系,Result<S>和Result<T>是沒有什么聯系的。

我們假設上述的泛型轉換是成功的,那么我們就可以通過re_person的引用,將Teacher類的相關信息設置到Result<Student> re_student這個對象中,這顯然是不允許的。

 

(一) 通配符類型------上界通配符<? extends T>

為了解決泛型這種使用起來的不便性,java泛型的設計者們引入了通配符"?"

比如Result<? extends Person>表示任何泛型Result類型,它的類型參數是Person以及Person的子類,如Result<Student>。

我們將上述的泛型轉換改為如下形式:

 

[html] view plain copy
  1. // Result<? extends Person>是Result<Student>的父類型  
  2. Result<Studentre_student = new Result<Student>(new Student(), new Student());  
  3. Result<? extends Personre_person = re_student;  

這種形式的轉換就是正確的,我們稱<? extends Person>為上界通配符


然而使用上界通配符也帶來了一些副作用:

我們看如下的代碼:

 

[java] view plain copy
  1. public static void main(String [] args){  
  2.     // Result<? extends Person>是Result<Student>的父類型  
  3.     Result<Student> re_student = new Result<Student>(new Student(), new Student());  
  4.     Result<? extends Person> re_person = re_student;  
  5.     Person person = re_person.getCode();  
  6.     //Error:The method setCode(capture#2-of ? extends Person) in the type Result<capture#2-of ? extends Person> is not   
  7.     //applicable for the arguments (Student)  
  8.     re_person.setCode(new Student);  
  9. }  

看起來域的訪問器setCode()方法無法使用
re_person.setCode(new Student);// Error
Result<? extends Person>的方法看起來是如下這樣的:

[java] view plain copy
  1. extends Person getCode() {  
  2.     return code;  
  3. }  
  4.   
  5. void setCode(? extends Person code) {  
  6.     this.code = code;  
  7. }  


setCode的形參是? extends Person code,但是不知道具體是什么類型這樣就無法傳遞特定的類型,也就無法調用setCode()方法了,畢竟通配符"?"不能匹配具體的任何類型。
而getCode()是能正常調用的,我們知道? extends Person代表的是Person的子類,這樣我們就可以把get到的值轉換成父類型Person。


(二) 通配符類型------下界通配符<? super T>

在上面中我們說,當使用上界通配符<? extends T>時,只能get數據而不能set數據;而下界通配符<? super T>剛好相反,當使用下界通配符時,只能set數據而不能get數據。

<? super Student> 表示將通配符限制為Student或者及其超類,如下圖所示:


 

當使用Result<? super Student>下界通配符時,其方法看起來是這樣的:

 

[java] view plain copy
  1. super Student getCode() {  
  2.     return code;  
  3. }  
  4.   
  5. void setCode(? super Student code) {  
  6.     this.code = code;  
  7. }  

對於set操作我們已經知道形式參數是Student或者Student的超類
那么我們就可以使用小於等於Student粒度的類型來傳遞參數

對於get操作 我們只知道返回值是Student或者Student的超類 但具體是什么類型我們不知道 所有我們無法
給具體的類進行賦值;只能賦值給Object對象

 

[java] view plain copy
  1. public static void main(String [] args){  
  2.     // Result<? super Student>為下界通配符  
  3.     Result<Student> re_student = new Result<Student>(new Student(), new Student());  
  4.     Result<? super Student> sre_student = re_student;  
  5.       
  6.     // Error:The method setCode(capture#4-of ? super Student) in the type Result<capture#4-of ? super Student> is not   
  7.     // applicable for the arguments (Person)  
  8.     sre_student.setCode(new Person());  
  9.       
  10.     // right operation  
  11.     // 對於set操作我們已經知道形式參數是Student或者Student的超類  
  12.     // 那么我們就可以使用小於等於Student粒度的類型來傳遞參數  
  13.     sre_student.setCode(new Graduate());  
  14.     sre_student.setCode(new Master());  
  15.       
  16.       
  17.     // Error:Type mismatch: cannot convert from capture#5-of ? super Student to Student  
  18.     // 對於get操作 我們只知道返回值是Student或者Student的超類 但具體是什么類型我們不知道 所有我們無法  
  19.     // 給具體的類進行賦值;只能賦值給Object對象  
  20.     Student student = sre_student.getCode();  
  21.       
  22.     // right operation  
  23.     Object object = sre_student.getCode();  
  24. }  


(三) 總結限定通配符的使用

<? extends T>:上界通配符 只能取數據而不能寫入數據

<? super T> :  下界通配符 只能寫入數據 取數據只能賦值給Object

如果你既想要獲取數據,又要寫入數據,那么你不能使用通配符類型變量,你可以嘗試使用固定的類型變量T,如果還不能解決你的問題,

那么不建議你使用泛型解決你的這個問題。


免責聲明!

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



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