Java 泛型類

文章目錄
     一、泛型類的由來
      當類中要操作的引用數據類型不確定的時候,
      早期定義Object來完成擴展
      現在定義泛型來完成擴展
     二、並不存在泛型類
     1、如何驗證不存在泛型類
     2、使用注意事項
     三、泛型繼承
     1、以泛型類爲父類
     2、以非泛型類爲父類
     3、泛型類與非泛型類在繼承時主要區別

一、泛型類的由來
當類中要操作的引用數據類型不確定的時候,
早期定義Object來完成擴展,
現在定義泛型來完成擴展。

(1)先看早期的做法,看個例子

public class GeremicClass
 {
	public static void main(String[] args) {
		Tools u = new Tools();
		//u.setObject(new Teacher());  類型轉化異常
		u.setObject(new Worker());
	    Worker w = (Worker)u.getObject();
	}
}

class Teacher
{	
}

class Worker
{	
}

class Tools
{
	private Object obj;
    public void setObject(Object obj){
    	this.obj = obj;
    }
    public Object getObject(){
    	return obj;
    }
}

(2) 定義泛型後的做法

public class GeremicClass {

	public static void main(String[] args) {
		Tools<Worker> u = new Tools<Worker>();
		//u.setObject(new Teacher());  類型轉化異常
		u.setObject(new Worker());
	    Worker w = u.getObject();
	}

}
class Tools<T>
{
	private T obj;
    public void setObject(T obj){
    	this.obj = obj;
    }
    public T getObject(){
    	return obj;
    }
}

分析 : 不需要進行類型強轉。在調用setObject方法時,如果我傳入的參數類型非Worker類型,編譯直接報錯。而早期通過定義Object來完成擴展,需要強轉,而且如果傳參類型出錯,只能到運行時體現。不利於定位問題。我們稱Tools爲自定義的泛型類。

二、並不存在泛型類
這個標題不是與上面的相違背。不急。先看一個簡單的例子。

	public static void main(String[] args) 
	{
		ArrayList<Teacher> l1 = new ArrayList<Teacher>();
		ArrayList<Worker> l2 = new ArrayList<Worker>();
		System.out.println(l1.getClass()==l2.getClass());
	}

你覺得上述代碼是輸出ture還是false呢?答案是true。

1、如何驗證不存在泛型類

不管泛型類型的實際參數是什麼,他們在運行的時候總會有相同的class,即系統並沒有生成新的class文件。 實際上,泛型對其所有可能的類型參數,都具有同樣的行爲,從而可以把相同的類當成許多不同的類來處理。

2、使用注意事項

<1> 因爲不存在泛型類,所以經過instanceof運算符處理後不能使用泛型類。
//下面的代碼編譯時會引發錯誤

	if(l1 instanceof ArrayList<Teacher>)
	{		
	}

<2> Java類中的靜態方法、靜態初始化、靜態變量聲明、初始化中不允許使用泛型參數。

三、泛型繼承
和普通類一樣,泛型類一樣支持繼承。任何一個泛型類都可以作爲父類或者子類。

1、以泛型類爲父類
當一個類的父類是泛型時,這個子類必須要把類型參數傳遞給父類,所以這個子類必定是泛型類。

// main方法
	public static void main(String[] args) 
	{
		SubTools<String> t1 = new SubTools<String>("hello java");
	    System.out.println(t1.getObject());
		
	}

//定義一個泛型類
class Tools<T>
{
	private T obj;
	public Tools()
	{	
	}
	//當程序員提供有參構造方法,系統將不會提供無參構造方法
    public Tools(T obj){
    	this.obj = obj;
    }
    public void setObject(T obj){
    	this.obj = obj;
    }
    public T getObject(){
    	return obj;
    }
}

//泛型類的子類(注意SubTools是如何聲明稱爲Tools的子類的。格式。)
class SubTools<T> extends Tools<T>
{
	public SubTools(T obj){
		 super(obj);  //調用的是父類有參構造方法。
		//super();  調用父類無參構造方法
	}
}

當然,除此之外,子類還可以擴展自己的類型參數。看下面一個例子

//泛型類的子類(注意SubTools是如何聲明稱爲Tools的子類的。格式。)
class SubTools<T,U> extends Tools<T>
{   
	public U extentsion;
	public SubTools(T obj,U ex){
		 super(obj);  //調用的是父類有參構造方法。
		//super();  調用父類無參構造方法
		 extentsion = ex;
		 
	}
	public U getExtension(){
		return extentsion;
	}
}
//main方法如下
public static void main(String[] args) {

	SubTools<String,Integer> t1 = new SubTools<String,Integer>("value is:",100);
	System.out.println(t1.getObject()+t1.getExtension());
   //輸出: value is:100
}

2、以非泛型類爲父類
泛型類也可以使用非泛型類作爲父類,此時不需要傳遞類型參數給父類,所有的類型參數都是爲自己準別的。

//定義一個泛型類,其父類不是泛型類
class GemericClass<T> extends Teacher{
	
	private T obj;
	public GemericClass(String name,T obj){
		super(name);
		this.obj = obj;
	}
	
	public T getObj(){
		return obj;
		
	}
}
// 非泛型父類
class Teacher
{	
   private String name;
   
   public Teacher(){
	   
   }
   public Teacher(String name){
	   this.name = name;
   }
   
   public String getName(){
	   return name;
   }
}

//main方法
public static void main(String[] args) {
  GemericClass<Integer> t1 = new GemericClass<Integer>("value is:",500);
  System.out.println(t1.getName()+t1.getObj());
  //輸出: value is:500
}

3、泛型類與非泛型類在繼承時主要區別
泛型類的子類必須將泛型父類所需要的類型參數,沿着繼承鏈向上傳遞。(類似於構造方法)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章