天天看點

建立一個泛型數組會發生什麼?嘗試建立一個泛型數組泛型與類型擦除數組與泛型

數組的使用頻率非常高,我們經常會建立一個數組,無論是基本類型還是引用類型的數組;但是你嘗試建立過泛型數組嗎?又會發什麼什麼?

嘗試建立一個泛型數組

如果你使用Java語言,并且嘗試建立一個泛型數組;好吧,其實你會發現根本無法建立一個泛型數組,編譯器在編譯階段就制止了你的這一行為。

建立一個泛型數組會發生什麼?嘗試建立一個泛型數組泛型與類型擦除數組與泛型

數組與泛型不能很好的結合,也不能建立具有泛型類型的數組。其中的原因與泛型的實作機制有關。

泛型與類型擦除

Java引入泛型的目的之一是指定容器要裝載的對象的類型,由編譯器來保證類型的正确性。這樣能一定程度保證代碼的安全性。

public static void main(String[] args) {
		List<Integer> list=new ArrayList<>();
		list.add(new Integer(1));  //OK
		//list.add("hello");   //Error
	}
           

雖然泛型功能強大并且能夠友善程式設計,但是它并不像我們想的那麼友好。親手編寫的代碼有時并不如你意,比如下面的例子:

public static void main(String[] args) {
		Class ca=new HashSet<Integer>().getClass();
		Class cb=new HashSet<String>().getClass();
		System.out.println(ca==cb);  //true
	}
           

一個是HashSet< Integer>,一個是HashSet< String>,輸出的結果卻是true,這似乎有點匪夷所思。

Java的泛型的實作依賴于 類型擦除 ,所謂擦除,就是在使用泛型時,類型參數(正如上面的Integer和String)會被自動忽略,是以,在真正運作泛型代碼的時候,ca和cb都是原生的HashSet類型,或者你可以認為它們都是HashSet< Object>類型(這種隻包含類型< T>的泛型會被擦除為最大的父類Object)

public static void main(String[] args) {
		Class ca=new HashSet<Integer>().getClass();
		Class cb=new HashSet<String>().getClass();
		System.out.println(ca);  //class java.util.HashSet
	}
           

是以,當你編寫類似上面的泛型代碼時,你必須深刻的知道,你能這麼寫隻是告訴編輯器将來要将Integer作用于HashSet,而它本質上隻是一個Object。

數組與泛型

由于擦除的存在,會掩蓋泛型數組的類型,而數組必須要知道确定的類型才可以使用,要不然會出現[1,“hello”,2.0]這樣的數組,當然是不允許的。

或許你有疑惑,根據擦除,上面的List[] ints=new List[5]實際上是List,這不也是确切的類型嗎?可是Integer,String都是Object,是以是不能這樣建立的。

雖然不能建立new一個數組執行個體,但是卻可以建立泛型數組的引用。通過非泛型的數組進行轉型也可以指派給泛型數組的引用。

public static void main(String[] args) {
		List<Integer>[] ints;  //泛型數組引用
		List[] ls=new List[5]; //非泛型數組
		ints=ls;               //指派,會自動轉型
		for(List l:ints) {
			l=new ArrayList<>();
		}
	}
           

上面是一個List這樣的泛型,不能直接建立;那麼可以T[]的數組可以實作嗎?答案是可以的。

當然你肯定不能直接T[] t;

public static void main(String[] args) {
	    T[] t=new T[5]; //T cannot be resolved to a type
	    //error
	}
           

你可以像下面這樣對數組本身類型進行執行個體化:

public static void main(String[] args) {
		Integer[] intA= {1,2,3,4};
		ArraryT<Integer> arrayT=new ArraryT<>();
		Integer[] ints=arrayT.getArrayT(intA);
		for(Integer i:ints) {
			System.out.print(i);  //1234
		}
	}

	//ArrayT類
	public class ArraryT<T> {
		public T[] getArrayT(T[] t) {
			return t;
		}
	}
           

是以,某種意義上說,不能建立泛型數組的說法并不準确。

不過Java有如此強大的容器類,更多時候應該選擇使用容器類,而不是數組。

個人部落格:http://smartpig612.club

微信公衆号:SmartPig