2015-05-18 56 views
7

我碰到下面的代碼,添加元素的一個簡單的例子來ListArrayList <Integer>允許添加String嗎?

List list = new ArrayList<Integer>(); 
    ListIterator<Integer> litr = null; 
    list.add("A"); 

    list.add("1"); 

    list.add(5); 

    litr = list.listIterator(); 
    while(litr.hasNext()){ 
     System.out.println("UIterating " + litr.next()); 
    } 

我希望它拋出一個ClassCastException,而是寫了這個控制檯

A 
1 
5 

看起來怪異。當我嘗試:

List<Integer> list = new ArrayList<Integer>(); 

我有一個編譯時錯誤。

我將不勝感激,如果有人可以解釋String對象是如何加入到ArrayList

+4

http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – CupawnTae

+4

http://stackoverflow.com/questions/2770321/what-is-a-raw -type-and-why-shouldnt-we-use-it – Reimeus

+1

我可以用一句話總結:「在Java中,泛型只能在編譯時完成。」話雖如此,Java會因此引發關於使用原始類型的警告。 – Powerlord

回答

4

您分配了新的ArrayList到非類型化的列表。泛型類型限制不適用於無類型的List,它會讓你隨意放置任何你想要的東西。編譯器不會跟蹤您的無類型List是否指的是使用泛型類型聲明的內容。

在任何情況下,這不會產生ClassCastException,泛型只會影響編譯。在運行時

,你把類型的列表中可變的情況下:

List<Integer> list = new ArrayList<Integer>(); 

是首選,它應該產生一個編譯器錯誤,告訴你,你把錯誤類型的收藏。

還有遺留,非通用代碼和通用代碼是如何在this article互操作的說明:

在適當的通用代碼,收集總是被一個類型參數陪同。當像Collection這樣的泛型類型沒有使用類型參數時,它被稱爲原始類型。

大多數人的第一本能是收集真的意味着Collection<Object>。但是,正如我們前面看到的,在需要Collection<Object>的地方通過Collection<Part>並不安全。更準確地說,Collection類型表示一些未知類型的集合,就像Collection<?>

但是等等,那也不行!考慮致電getParts(),它返回一個集合。然後將其分配給k,這是一個Collection<Part>。如果調用的結果是Collection<?>,則分配將是錯誤。

實際上,這項任務是合法的,但它會產生一個未經檢查的警告。該警告是必需的,因爲事實是編譯器不能保證其正確性。我們無法檢查getAssembly()中的遺留代碼,以確保返回的集合確實是部分集合。代碼中使用的類型是集合,並且可以合法地將各種對象插入到這樣的集合中。

那麼,這不應該是一個錯誤?從理論上講,是的。但實際上,如果通用代碼要調用遺留代碼,則必須允許這樣做。編程人員應該確信,在這種情況下,作業是安全的,因爲合同getAssembly()表示它返回了一組部件,即使類型簽名沒有顯示這一點。

+0

僅供參考:您應該在報價中的代碼周圍放置代碼塊。 否則,你看不到其中的一個收藏是'Collection ' – Powerlord

+0

@Powerlord:對,謝謝 –

+0

@NathanHughes謝謝你的回答。瞭解了無類型列表和原始收集 –

1

這是可能的,因爲泛型是如何在Java中實現 - 用type erasure,因爲Java支持raw types與舊版本的Java(1.4及以上)的向後兼容性。

泛型只存在於您的源代碼中。編譯器使用它們在編譯時檢查類型,但隨後拋棄泛型。在運行時,List<Integer>只是對象的List,它不知道它是隻包含Integer對象的列表。

Java支持使用原始類型,例如List而不是List<Integer>以與舊版本向後兼容。當你使用原始類型時,就像你在上面的代碼中做的那樣,你會得到一個編譯器警告。您不應該在新代碼中使用原始類型 - 只有在您需要處理舊代碼時纔會使用它們,而這些代碼是無法更改的。

原始類型和類型擦除的組合允許您將列表中的對象類型放入列表中,而不應放在那裏。

由於List在運行時不知道其元素應該具有的類型,因此它不檢查任何內容,因此您不會得到ClassCastException

相關問題