2016-11-17 67 views
2

爲什麼這個代碼編譯:爲什麼ArrayList的<E>構造允許原始的ArrayList參數

ArrayList strings = new ArrayList(); 
strings.add("s1"); 
strings.add("s2"); 

ArrayList<Integer> numbers = new ArrayList<Integer>(strings); 

鑑於所涉及的構造函數需要一個Collection<? extends E>其中E在這種情況下是整型?如何將原始類型ArrayList中的對象包含在E的子類中?或者是否有一些隱藏的編譯器魔術可以實現這一目的?

+1

我想這是因爲兼容性。由於編譯器無法知道哪些對象在「字符串」中,因此它假定其中存在正確的對象。 如果編譯器的行爲不同(並且不允許這樣做),那麼從(舊)非泛型使用代碼到泛型的改變幾乎是不可能的。 –

+0

這只是衆所周知的原始類型轉換的一個實例:'列表 numbers = new ArrayList();'。 –

回答

2

檢查ArrayList構造:

public ArrayList(Collection<? extends E> c) { 
    elementData = c.toArray(); 
    if ((size = elementData.length) != 0) { 
     // c.toArray might (incorrectly) not return Object[] (see 6260652) 
     if (elementData.getClass() != Object[].class) 
      elementData = Arrays.copyOf(elementData, size, Object[].class); 
    } else { 
     // replace with empty array. 
     this.elementData = EMPTY_ELEMENTDATA; 
    } 
} 

elementData是對象的數組:

transient Object[] elementData; 

所以新ArrayList(Collection<? extends E> c)將接受所有Collection,不在乎E

它將當我們使用它時拋出ClassCastExceptionwhen

Integer i= numbers.get(1); 
+0

這並不能解釋原始'ArrayList'中的元素如何滿足'?擴展E'。 –

1

編譯器應該給你這樣的警告:

類型安全:ArrayList類型的表達式需要選中 轉換爲符合Collection<? extends Integer>

說,也有一些是錯誤的給定參數(字符串)。

你也應該在嘗試運行代碼時,此異常:

java.lang.ClassCastException:java.lang.String中不能轉換爲java.lang.Integer的

沒有編譯錯誤的原因是ArrayList字符串沒有正確定義,所以省略了String類型。所以編譯可能只會猜測有什麼worng。更改您的代碼

ArrayList<String> strings = new ArrayList<String>(); 

,你會得到編譯錯誤

構造ArrayList<Integer>(ArrayList<String>)未定義

相關問題