第二十五條:列表優先於數組

一、數組與列表容器的比較

①、協變與不可變類型:
數組:是協變類型的。協變的意思就是Number是Integer的父類,那麼Number[] data = new Integer[]; 是成立的。
列表:是不可變類型。就是說無法List<Number> list = new List<Integer>();
無法發生協變纔是正確的方式。原因:
	public static void main(String[]args){
		Object[] obj = new Long[10];
		obj[0] = "Is right";
		//運行時候報錯:java.lang.ArrayStoreException
		
		List<Object> data = new ArrayList<String>();
		//直接報錯
	}
②、運行時檢驗與編譯器檢驗。
數組:運行時檢驗。因爲數組在編譯使其創建的類是具體化的。然後在運行期間檢驗類型約束是否正確。所以就會產生將String類添加到Long類型的數組中會在運行時報java.lang.ArrayStoreException的錯誤。感覺這個模式是特定針對數組的協變而創造的,因爲數組在編譯器中也是會受檢驗報錯的。比如說:
	public static void main(String[]args){
		Integer[] data = new Integer[10];
		data[0] = 3.14;//在編譯器直接報錯
	}
泛型:編譯期檢驗。因爲泛型會在運行的過程中參數類型會被擦除,所以必須在編譯期就得保證類型安全。這就不容許有協變這個性質。

二、數組與泛型無法結合使用

數組與泛型的結合:new List<String>[]、new E[] 都是錯誤的。
因爲數組是在運行期檢驗的,但是運行期間泛型會被擦除,從而導致Java虛擬機無法判斷類型的安全性。
同時由於數組是運行期檢驗,所以具有協變的特性。這也導致了泛型無法與數組結合。
例:
	public static void main(String[]args){
		List<String> strList = new ArrayList<String>();
		List<Integer> intList = new ArrayList<Integer>();
		
		List<String>[] strArray = new List<String> [10];//假設允許泛型數組
		List<Integer>[] intArray = new List<Integer>[10];
		
		Object[] obj = strArray;
		obj[0] = intList; //將intList存入了strArray中。 與剛纔的協變的例子是一樣的
		
		List<String> str = strArray[0].get(0);
	}

從技術上來說,泛型是不可具體化的。
不可具體化:運行期間虛擬機獲得的信息不能夠比編譯期間更多(擦除導致的問題)。
只有通過無限通配符(?)才能讓泛型變爲具體化
由於這一特性,導致使用泛型的數組(T[] a)和利用泛型轉型((T) a)是類型不安全的,因爲虛擬機根本不知道轉化成那種類型。
所以對泛型使用可變參數列也是不安全的。
例:
public class Test <E> {

	//產生不安全的警告
	public void get(E ... dataEs){
		
	}
}

例如:現有有一個方法通過其他方法操縱數組的四則運算。
	//假設進行加法運算。
	public int handleList(List<E> list,Function<E> function,int initalVal){
		E[] datas = (E[])list.toArray(); //類型不安全的警告。
		int result = initalVal;//初始數據
		for(E data : datas){
			result = function.apply(result,data);
		}
		return result;
	}
爲了消除這種安全警告,只能用上註解。但是如果使用上了列表容器就能夠直接消除警告了
	public int handleList(List<E> list,Function function,int initalVal){
		List<E> datas = new ArrayList<E>(list);//消除警告
		int result = initalVal;//初始數據
		for(E data : datas){
			result = function.apply(result,data);
		}
		return result;
	}
所以說,儘量使用列表。但是如果必須使用數組來提高效率的話,只有加上註解這一個方法。










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