2015-10-14 84 views
1

我正在瀏覽這個頁面,只是玩它提供的例子。類型擦除 - 泛型 - 得到ClassCastException不在預期的地方

http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html

我使用Java 8

根據本教程頁面,則ClassCastException應在該行200被拋出,但實際上它是較早拋出 - 在標記爲100爲什麼行? !該教程是否過時(不適用於Java 8)?

然後,我問的n所有方法,我可以看到該方法setData(Object)是存在的,它是在對象指向n(這就是所謂的電橋法,我認爲)。

好的,那麼爲什麼我會在標記爲100的行上得到異常呢?編譯器是否將我的設置變爲這個n.setData((Integer)"Hello");如果是這樣,看起來教程確實已經過時了。

任何人都可以解釋這一點嗎?

import java.lang.reflect.Method; 

public class Test010 { 

    public static void main(String[] args) { 
     MyNode mn = new MyNode(5); 
     Node n = mn; // A raw type - compiler throws an unchecked warning 
     Method meth[] = n.getClass().getMethods(); 
     n.setData("Hello"); // 100 // 
     System.out.println("001"); 
     Integer x = mn.data; // 200 // // Causes a ClassCastException to be thrown. 
    } 

} 

class Node<T> { 

    public T data; 

    public Node(T data) { 
     this.data = data; 
    } 

    public void setData(T data) { 
     System.out.println("Node.setData"); 
     this.data = data; 
    } 
} 

class MyNode extends Node<Integer> { 

    public MyNode(Integer data) { 
     super(data); 
    } 

    public void setData(Integer data) { 
     System.out.println("MyNode.setData"); 
     super.setData(data); 
    } 
} 

回答

4

好的,好吧,我在發佈問題後不久就想到了。

實際上在第200行引發的異常:這不是事實,本教程只是假設性地提到這一點。在本教程中,很明顯橋setData方法包含類型轉換爲Integer

public void setData(Object data) { 
    setData((Integer) data); 
} 

這就是我的問題和我的困惑。

在任何情況下,這個教程頁面似乎有點混亂,但好吧,也許這只是我。

1

我傾向於說教程是錯誤的。如果類MyNode沒有涉及,或者如果MyNode一般繼承Node<T>,而不是具體指定類型參數,那將是正確的。一旦MyNode爲類型參數定義了一個特定的值,但是類型擦除不再適用於它。

+0

現在你讓我更加困惑,不久之後,我想我找到了它:) –

+0

@ peter.petrov,我不認爲我說任何與你自己的答案衝突的東西。在你的問題中,有一個例外是,並且總是被拋到標有'100'的行。雖然類型擦除不直接應用於類「MyNode」,但本教程指出它必須適應*類適用於類「節點」的類型擦除。爲了處理這個問題,編譯器合成一個橋接方法。 –

+0

我明白了......好的,這個評論讓我更清楚一點,我想。 –