2014-09-05 170 views
4

最近我看了一段看起來很奇怪的代碼。正如我們所知道的,當我們需要使用它們時,我們需要在集合中初始化泛型類型。另外,我們知道集合可以包含集合作爲其元素。ArrayList Generic without Type

代碼:

public class Solution { 
public static void main(String args[]) { 
    ArrayList res = returnlist(); 
    System.out.print(res.get(0)); 
} 
public static ArrayList<ArrayList<Integer>> returnlist() { 
    ArrayList result = new ArrayList(); 
    ArrayList<Integer> content = new ArrayList<Integer>(); 
    content.add(1); 
    result.add(content); 
    return result; 
}} 

我的問題是

  • 我們爲什麼可以使用ArrayList result = new ArrayList();創建一個對象,因爲我們還沒有給集合的實際類型的元素。
  • 我們爲什麼可以使用result.add(content);到集合添加到集合與集合「結果」只是一個普通的集合。我們沒有把它定義爲一個ArrayListArrayList

回答

7

爪哇通用集合不存儲與一種類型以確保向後預J2SE 5.0兼容性。類型信息在添加到通用集合時被刪除。這被稱爲Type Erasure

這意味着,一個通用的集合可以被分配到一個非通用的參考。

所有Java泛型確實是確保你不能錯誤的類型添加到一個通用的列表,並從做一個explicit投上檢索您節省;即使它仍然完成implicitly

進一步就此

+1

+1我認爲這是最有意義的答案 – ne1410s 2014-09-05 16:03:27

+1

+1認可。@ ne1410s – Kai 2014-09-05 16:05:32

+0

2 +1但只有1分...已經StackOverflow失去了計數能力? :P – 2014-09-05 16:07:29

0

它可能是從仿製藥來了到Java之前的殘餘(Java的4或5,我認爲)。

+0

不一定是殘餘,但肯定是不使用泛型的功能。您必須在結果上投射這些項目才能在獲得它們時使用它們。 – 2014-09-05 15:55:54

+0

是的。似乎我們需要照顧我們存儲在沒有泛型的ArrayList中的事物。 – Kai 2014-09-05 16:00:17

0

泛型添加到Java只在Java 5在此之前,當你使用一個集合,它總是意味着對象的集合。舊的語法保留爲了向後兼容。所以ArrayList result = new ArrayList()實際上是創建一個ArrayList<Object>。由於ArrayList也是一個對象,因此可以將content添加到變量result

+0

有道理。但在日常編程中,它仍然是一種非常流行的方式來使用不帶泛型的集合? – Kai 2014-09-05 15:59:27

+0

不建議用於新的代碼。但是在Java 5之前編寫了很多代碼,並且在維護代碼甚至擴展它時,人們傾向於使用舊的風格。 – 2014-09-05 16:03:22

+0

非常感謝。 – Kai 2014-09-05 16:07:28

0

爲什麼我們可以用ArrayList result = new ArrayList();來創建一個對象,因爲我們沒有給這個集合實際的元素類型。

因爲基於java希望它向後兼容。泛型更多的是確保類型安全的編譯器特性,集合可以在運行時存儲任何類型的對象。

Java編譯器不會給你編譯器錯誤此,但它一定是給你編譯器警告,這是不安全的使用泛型類沒有類型。

2

只要加上p rovide總結答案

老辦法:

(A) ArrayList result = new ArrayList(); 

將創建一個ArrayList舉辦 「對象」


新途徑:

ArrayList<Integer> content = new ArrayList<Integer>(); 

這代表一個ArrayList將舉行「整數」對象。這是爲編譯時類型檢查目的而引入的。


爲什麼?

考慮第一種情況。它的輸入類型是Object。我們知道Object是所有類的超類。我們可以傳入一個Integer對象,String對象等等。獲取數據時,開發人員必須執行正確的類型轉換。如果說開發商一開始認爲的代碼將接受Integer對象,所以他增加了以下類型轉換而獲取

Integer integer=(Integer) content.get(0); 

這應該是工作數據。但是如果錯誤地傳遞了一個字符串,將會導致運行時錯誤。

如何避免?

通過引入編譯時檢查


它是如何工作的?

當我們只指定參數化類型時可以將Integer對象添加到ArrayList集合中。否則會顯示錯誤。

content.add(3); // will work 
content.add("HARSHAD"); // error shown 

如果參數泛型類型是類型檢查的目的數據如何正確可以從列表中檢索到的?

編譯器隱式執行類型轉換。請參閱示例代碼

List<Integer> list=new ArrayList<Integer>(); 
list.add(1); 
list.add(2); 
Integer integer=list.get(0); 
System.out.println(integer); 

執行編譯時編譯器實際執行的操作是什麼?

//perform type erasure 
(B) List list=new ArrayList(); 
    list.add(1); 
    list.add(2); 

// the arraylist inturn accepts Object when you run the code 

//add casting 
Integer integer=(Integer)list.get(0); 

結論

如果你看到的代碼(A)和(B)兩者是相同的。唯一不同的是,在第二種情況下,編譯器隱式執行相同的操作。

最後回答你的問題......

ArrayList result = new ArrayList(); 

是允許向後兼容。雖然這不被推薦。

官方鏈接Oracle docs解釋相同的概念。