java泛型學習-泛型的產生原因,使用方法以及具體的警告
如果缺乏能力,自由反而是一種負擔 --使用Ubuntu有感
看魔樂的李興華JAVA視訊,視訊倒是幾年前百度雲就存好了,也放在電腦上好久了.最近在重新補習JAVA,正好翻到了這些視訊,
從接受的角度而言,視訊講解比看書要容易得多,只是自己一直有一種強迫症似的感覺,喜歡看書學習.
殊不知這是效率最低的方法,今天學的知識點其實時一個小時就能搞懂的知識點,但是因為知識缺陷的原因此前看到別的程式碼裡面的泛型,都是頭大的看不懂.
學習啊!方法很重要,不能有知識缺陷,先不求深入,但是框架脈絡總得捋一遍.
今天甚至翻到了B站竟然有一系列的學習IT相關的視訊,感覺對B站越來越有好感了,都是一些很有趣的視訊,不會讓人有心理負擔.其實,我這麼逃避學習大概是因為怕自己投入了也學不好,所以乾脆逃避,o,the biggest deny is delay!!
進入正題:
1為什麼要有泛型?保證資料的安全性
特別是如果在一個類內部,成員變數一開始不知道用的時候會賦值為什麼型別的時候,會非常頭痛,型別轉換也是個大問題.
2因此在類名的旁邊宣告一個型別,用字母加尖括號表示,如<T>,而這個T可以在類內部使用,編譯執行的時候替換成具體的型別.簡單的說,就是使用類的時候先宣告泛型的型別;
通過這種方式,在使用類的時候可以宣告構造的類中該泛型表示的具體的型別,減少型別轉換的操作,更加安全,如果賦值與宣告的型別不一質量,則編譯的時候就會報錯.
可以通過構造方法為成員變數賦值,這樣的好處時不需要進行多次的構造方法的過載,直接一個泛型替代了
3
class xxx<a,b,c>{
}
4泛型的安全警告
在使用帶泛型的類的時候,沒有指定泛型的型別,會有編譯警告.因為不確定傳入的時什麼值,但不會影響執行,因為在java中為了不影響使用,如果沒有指定泛型的型別,就會將T替換成Object,
泛型的萬用字元
1泛型物件進行引用傳遞的時候,型別必須一致,如果現在非要傳遞,可以將方法的引數中的泛型型別取消掉,,
2可以用?來代替
3使用<?>只能接收,不能修改???
class Info<T>{ private T var ; public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } public String toString(){ return this.var.toString() ; } }; public class GenericsDemo15{ public static void main(String args[]){ Info<?> i = new Info<String>() ; //單此一句用問號接收這個型別的物件是可以 i.setVar("MLDN") ; //但是加上這一句賦值的就編譯報錯. } };
4萬用字元的限制
受限泛型:在引用傳遞中,泛型操作可以設定一個泛型物件的範圍上限和範圍下限,範圍上限使Eextends關鍵字宣告,表示引數化的型別可能是說指定的型別或者此型別的子類,
而範圍下限使用super宣告,表示來引數化型別可能是指定的型別或者時次型別的父型別,直至object類.
class Info<T>{
private T var ;
public void setVar(T var){
this.var = var ;
}
public T getVar(){
return this.var ;
}
public String toString(){ // Ö±½Ó´òÓ¡
return this.var.toString() ;
}
};
public class GenericsDemo18{
public static void main(String args[]){
Info<String> i1 = new Info<String>() ; //
i1.setVar("hello") ;
fun(i1) ;
}
public static void fun(Info<? extends Number> temp){ // 最多隻能傳遞到NUMBER這一型別
System.out.print(temp + "¡¢") ;
}
};
//--------------------------------------------------分割線
class Info<T extends Number>{//只能傳遞數字
private T var ;//
public void setVar(T var){
this.var = var ;
}
public T getVar(){
return this.var ;
}
public String toString(){//
return this.var.toString() ;
}
};
public class GenericsDemo19{
public static void main(String args[]){
Info<Integer> i1 = new Info<Integer>() ;// 正確的
Info<String> i1 = new Info<String>() ;//錯誤的
}
};
泛型的下限:
class Info<T>{
private T var ; // 定義泛型變數
public void setVar(T var){
this.var = var ;
}
public T getVar(){
return this.var ;
}
public String toString(){ // 直接列印
return this.var.toString() ;
}
};
public class GenericsDemo21{
public static void main(String args[]){
Info<String> i1 = new Info<String>() ; //宣告String的泛型物件
Info<Object> i2 = new Info<Object>() ; // 宣告Object的泛型物件
i1.setVar("hello") ;
i2.setVar(new Object()) ;
fun(i1) ;
fun(i2) ;
}
public static void fun(Info<? super String> temp){ // 只能接收String以及其父類Object
System.out.print(temp + "xx") ;
}
};
泛型與子類繼承的限制:
一個類的子類可以通過物件多型性,為其父類例項化,但是在泛型操作中,子類的泛型時無法使用父類的泛型型別來接受的,例如
Info<String> 不能使用 Info<Object>接收,就是泛型使用必須精準,上下限只起到一個列舉的作用
如以下程式碼不行
Info<String> i1 = new Info<String>() ;
Info<Object> i2 = null ;
i2 = i1 ;
這樣會擴大子類中型別,不行
但是使用?可以接收任意的泛型物件.