1. 程式人生 > >java泛型學習-泛型的產生原因,使用方法以及具體的警告

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 ;

這樣會擴大子類中型別,不行

但是使用?可以接收任意的泛型物件.