2013-10-06 54 views
0

我有一些關於橋樑方法創建的問題。我們可以將橋技術用於協變覆蓋。現在考慮來自官方幫助的示例:創建橋樑方法

public class Node<T>{ 
    private T data; 
    public Node(T data){ this.data=data;} 
    public void setData(T data){ 
     System.out.println("Node.setData"); 
     this.data=data; 
    } 
} 
public class MyNode extends Node<Integer>{ 
    public MyNode(Integer data){ super(data); } 
    public void setData(Integer data){ 
     System.out.println("MyNode.setData"); 
     this.data=data; 
    } 
} 

讓bridge方法不創建。因此,在運行時,類MyNode有兩種方法:setData(Integer)setData(Object),其中最後一個從Node繼承。當我們撥打setData(new Inetegr(5))時會撥打setData(Integer)。如果我們寫Object o= new Integer(5); setData(o);那麼將調用setData(Object)。這不是真的。 所以有兩個問題:

  1. 我明白導入橋接方法正確的原因嗎?
  2. 創建橋樑方法的必要條件和足夠的條件是什麼?
+0

你好 - 也許你會從這裏閱讀答案大大受益:http://stackoverflow.com/questions/5007357/java-generics-bridge-method – Meesh

回答

2

我明白引入橋接方法的理由嗎?

我想是的。如果編譯器沒有生成橋接方法,那麼子類中的方法將是超類方法的重載版本,而不是重寫的版本。你似乎已經明白了。

創建橋樑方法的必要條件和足夠的條件是什麼?

當您擴展或實現參數化類型,並鍵入擦除更改超類中方法的簽名。

如果我們寫Object o= new Integer(5); setData(o);則調用setData(Object)。這不是真的。

我不明白你是什麼意思。您應該在非泛型代碼上測試此行爲。當一個方法被重載時,然後一個方法調用被綁定到哪個方法是在編譯時根據你傳遞的參數的聲明類型來決定的。由於在這種情況下聲明的類型是Object,它將調用setData(Object)版本。

+0

_我不明白你說的是什麼意思_讓我們有原始類型聲明'Node m = new MyNode(5);對象o =新整數(5); m.setData(O);'。選擇虛擬方法的具體實現是在運行時按對象類型來確定。但'setData(Object)'方法在'MyNode'中沒有重載。因此'Node'的方法將被調用。 –

+0

_擴展或實現參數化類型時,輸入erasure會更改超類中方法的簽名。但在協變覆蓋的情況下,我們可能沒有參數化類型。但橋樑方法正在創建。沒有其他條件可以創建橋樑方法,不是嗎? –

1

這是編譯誰應用橋技術,而不是我們。根據你的情況,編譯器會在這裏插入橋

class MyNode extends Node<Integer> { 
    public void setData(Object data) { 
    setData((Integer) data); 
    } 
... 

,這就是爲什麼它被用來

Node<Integer> n = new MyNode(); 
    n.setData(1); 

節點沒有使用setData(整數),它具有使用setData(對象)。 MyNode橋接方法setData(Object)覆蓋它。 JVM檢測到n的實際類型是MyNode,並調用將重定向到setData(Integer)的MyNode.setData(Object)。

施加橋方法時的另一種情況是協變返回類型需要

class X implements Cloneable { 
    @Override 
    pubic X clone() { 
     ... 
    } 

橋實際重寫Object.clone。請注意,在字節碼方法簽名包括返回類型