[英]Different Java behavior for Generics and Arrays
為什么Java允許將不一致的類型輸入到通用對象引用中而不是數組中?
例如:
初始化數組時:
int[] a = {1, 2, 3};
而且,如果我輸入:
int[] a = {1, 2, "3"}; //Error for incompatible types
對於仿制葯,
import java.util.ArrayList;
public class Test {
private static ArrayList tricky(ArrayList list) {
list.add(12345);
return list;
}
public static void main(String[] args) {
int i = 0;
ArrayList<String> list = new ArrayList<>();
list.add("String is King");
Test.tricky(list);
}
}
上面的代碼將使您可以在list
對象中添加任何Type
,在某些情況下會導致運行時異常。
為什么會有這種行為? 請給一個適當的解釋。
該方法的參數沒有泛型,因此允許所有類。 您可以在Google上輸入“類型擦除”以獲取更多信息。
如果將泛型添加到方法中,則會出現編譯器錯誤:
private static ArrayList<String> tricky(ArrayList<String> list) { // ...
順便說一句,您不需要返回列表,因為您修改了同一實例。
原因如下:
之所以無法為數組編譯它,是因為存在運行時異常(ArrayStoreException),它將阻止您將錯誤類型的對象放入數組中。 如果將Dog數組發送到采用Animal數組的方法中,並且僅將Dogs(當然包括Dog子類型)添加到Animal現在引用的數組中,就沒有問題。 但是,如果您確實嘗試將Cat添加到實際上是Dog數組的對象中,則會出現異常。 通用方法(考試目標6.3和6.4)615616第7章:通用方法和集合
但是由於類型擦除,泛型沒有等效的例外! 換句話說,在運行時JVM知道數組的類型,但是不知道集合的類型。 所有通用類型信息在編譯過程中都會被刪除,因此,當它到達JVM時,根本無法識別將Cat放入ArrayList的災難,反之亦然(這就像您遇到的問題一樣)您使用傳統的非類型安全代碼)
禮貌:Kathy Sierra和Bert Bates撰寫的SCJP學習指南
當您聲明ArrayList就像ArrayList list = ...
您不會聲明列表將包含的對象類型。 默認情況下,由於每種類型都有Object
作為超類,因此它是ArrayList<Object>
。 為了好的做法,應該聲明ArrayList<SomeType>
的類型,從而避免添加不一致的元素(根據類型)
由於尚未定義列表的通用類型,因此默認為List<Object>
,它接受擴展Object
。
通過自動裝箱,將原始int
轉換為Integer
,當將Object
添加到列表中時,該Integer
擴展了Object
。
您的數組僅允許使用int
,因此不允許使用String
。
這是因為在方法參數中沒有為ArrayList指定特定類型,因此默認情況下它可以接受所有類型的對象。
import java.util.ArrayList;
public class Test {
//Specify which type of objects you want to store in Arraylist
private static ArrayList tricky(ArrayList<String> list) {
list.add(12345); //This will give compile time error now
return list;
}
public static void main(String[] args) {
int i = 0;
ArrayList<String> list = new ArrayList();
list.add("String is King");
Test.tricky(list);
}
}
當您使用tricky
方法將數據插入到ArrayList
集合中時,它與指定的類型(即String
不匹配,但是仍然兼容,因為泛型與舊的舊版代碼兼容。
如果不是這個原因,即如果它與數組的方式相同,那么所有Java之前的通用代碼都將被破壞,所有代碼都必須被重寫。
記住泛型的一件事,所有type-specifications
都是編譯時限制的 ,因此,當您使用tricky
方法在list
引用中插入數據時,編譯器將其視為一個列表,除原語外,其他任何內容都可以添加。
僅當您編寫以下內容時:
...
public class Test {
private static ArrayList tricky(ArrayList<String> list) {
list.add(12345); //Error, couldn't add Integer to String
return list;
}
...
}
我已經為此寫了一篇文檔化的文章,請閱讀此處 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.