泛型(泛型擦除)

泛型java

1.什麼是泛型安全

2.泛型類、泛型接口、泛型方法併發

3.爲何要使用泛型,泛型的好處spa

4.使用泛型注意點code

5.泛型擦除對象

 

1.什麼是泛型blog

1.1泛型概念:Java泛型是J2 SE1.5中引入的一個新特性,其本質是參數化類型,也就是說所操做的數據類型被指定爲一個參數(type parameter),接口

這種參數類型能夠用在接口和方法的建立中,分別稱爲泛型類、泛型接口、泛型方法。get

1.2本質:參數化類型編譯器

1.3語法:<T>,  T 稱爲類型佔位符,表示一種引用類型。

1.4特色:(1)編譯時便可檢查,非運行時拋出異常;

     (2)訪問時不須要類型轉換(拆箱);

     (3)不一樣泛型之間不能相互賦值,泛型不存在多態。

 

對於泛型特色(1)舉個例子 : 沒有使用泛型時的異常拋出

public class MyGenericTest {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(123);       //添加Integer對象
        list.add("zifu");    //添加String對象
        list.add(1.22);      //添加Double對象
        
        for(Object object: list) {
            //!!!使用,例如要進行運算使用
            Double num = (Double)object;
            System.out.println(num);
        }
    }
}

結果:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
    at MyGenerics.MyGenericTest.main(MyGenericTest.java:28)

分析一下:編譯經過,可是運行提示異常,類型轉換異常,就是String類型不能轉換爲Double類型。咱們在使用 list.add() 方法時,根據提示知道凡是Object對象均可以添加進去,可是要使用的時候忘了添加過什麼類型的對象進去,根據提示強轉過,可是因爲添加進去一些類型不一樣的,強轉能夠在編譯時經過,運行時異常拋出了。

這裏就能夠體現泛型的好處之一了:防止類型轉換異常,提升代碼的安全性。

 

 

對於泛型特色(2)訪問時不須要類型轉換(拆箱),舉例子List<String>  list =  new ArrayList<String>();

查看ArrayList的訪問4方法get()源碼,看到返回值類型是泛型E,因此咱們獲取時就不用強轉了。

 

 

 

package MyGenerics;

import java.util.ArrayList;
import java.util.List;

public class MyGenericTest {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("dingdong");		
		list.add("zifu");	
		list.add("meimei");		
		
		for(int i = 0; i < list.size(); i++) {
			//!!!使用
			String str = list.get(i);  //訪問時不須要類型轉換
			System.out.println(str);
		}
	}
}

 

對於泛型特色(3)不一樣泛型之間不能相互賦值,舉例

 

  對於泛型特色(3)泛型不存在多態,舉例

另外這裏報錯緣由是:Type mismatch: cannot convert from ArrayList<Integer> to ArrayList<Number>,類型不匹配的願意

 

2.泛型類、泛型接口、泛型方法

2.1泛型類

語法:類名<T,........>

舉例:

package MyGenerics;

import java.util.List;

//Generic類,泛型類
//語法:類名<T>
public class MyGeneric <T>{
	//添加屬性(泛型屬性變量)
	T t;
	//添加方法(泛型參數)
	public void show(T t) {
		System.out.println(t);
	}
	//添加方法(泛型作爲返回值)
	public T getT() {
		return t;
	}
}

 2.2泛型接口與泛型類類似,不舉例子了

語法:接口名<T, .......>

2.3泛型方法

語法:[ 修飾符] <T> 返回值類型 方法名([參數列表])

 

2.4.疑惑,爲何有泛型類了,還要有泛型方法,泛型類與泛型方法有什麼區別,泛型方法有什麼好處?

 爲何要使用泛型方法呢?(想換類型時,考慮方法的調用方便的好處,而類須要實例化)

由於泛型類要在實例化的時候就指明類型,若是想換一種類型,不得不從新new一次,可能不夠靈活;而泛型方法能夠在調用的時候指明類型,更加靈活。

 

3.爲何要使用泛型,泛型的好處:

3.1泛型的好處

答:提升代碼重用性,防止類型轉換異常,提升代碼的安全性。(也能夠加上泛型特色(1)(2))

3.2泛型類的好處

答:使用泛型類能夠解決重複業務的代碼的複用問題,也就是業務顆粒的複用,同時使用泛型類型在編譯階段就能夠肯定,並發現錯誤,類型的轉換都是自動和隱式的,提升了代碼的準確率和複用率。

 

4.使用泛型注意點:

4.1不一樣泛型之間不能相互賦值,泛型不存在多態((檢查機制)泛型特色(3))

4.2要注意泛型擦除

 

5.泛型擦除

 

5.1 泛型擦除概念: 類型擦除指的是經過類型參數合併,將泛型類型實例關聯到同一份字節碼上。編譯器只爲泛型類型生成一份字節碼,並將其實例關聯到這份字節碼上。類型擦除的關鍵在於從泛型類型中清除類型參數的相關信息,而且再必要的時候添加類型檢查和類型轉換的方法。

簡單理解:在編譯期間,全部的泛型信息都會被擦除掉。例如代碼中定義的List<Object>和List<String>等類型,在編譯後都會變成List。JVM看到的只是List,而由泛型附加的類型信息對JVM來講是不可見的。

 

5.2 因爲泛型擦除出現的錯誤舉例:

 報錯緣由:Erasure of method MyGeneric(ArrayList<String>) is the same as another method in type MyGeneric<T>,

Erasure of method MyGeneric(ArrayList<Integer>) is the same as another method in type MyGeneric<T>

類型擦除的緣由,擦除後        //方法重載,都變成了

  public MyGeneric(ArrayList  arrayList) {
        
    }

 

完美解釋此處問題,可是卻勾起小夥伴的另一個問題,類型擦除了,爲何不一樣泛型之間不能相互賦值!!

由於檢查機制的存在,編譯器的工做是這樣子滴:首先進行類型檢查,檢查類型不一樣,報錯!若是類型相同,再進行類型擦除啦!!!(即進入擦除階段,須要經過檢查那一關)

舉個例子,購買的衣服,須要相關人員先進行質量合格等方面的檢查,檢查經過,進入商城,消費者購買完撕掉了吊牌。。。。。

相關文章
相關標籤/搜索