2014-02-21 136 views
0

假設你有兩類:Java和動態類型

public abstract class X { 
    public abstract void insert(Object item); 
} 

public class Y extends X { 
    protected Object a; 
    public void insert(Object item) { 
    a = item; 
    } 
} 

當您嘗試以下方法:

X x = new Y(); 
x.insert(5); 

一切都很好。然而,當你還可以添加

x.a; 

爲什麼你要做的:

((Y) x).a; 

的最後一行?

預先感謝您!

回答

0

方法/字段解析是基於參考變量的類型(在這種情況下爲X)完成的。 'a'在X上不存在,因此您必須將其轉換爲Y以告知編譯器將該引用當作Y引用來處理,並且可以解析'a'。

+0

你能詳細說一下嗎? –

4

但是,編譯器是否應該認識到x的動態類型實際上是Y?

不,編譯器不分析程序來確定動態變量類型。在編譯時間,它只適用於靜態類型。

它似乎理解這第二行,因爲插入方法實際上最終給x一個「a」的值。

方法分辨率爲運行時,其中動態類型是可能完成的。這不是編譯器在執行分辨率,而是運行時。

0

動態綁定在這裏無關緊要。靜態綁定是重要的事情。

當您定義對象eas X x = ...時,您的對象具有類型爲X的靜態綁定。編譯器不知道該類型中的任何a

0

讓假設你有這樣的代碼:

public abstract class X { 
    public abstract void insert(Object item); 
} 

public class Y extends X { 
    protected Object a; 
    public void insert(Object item) { 
    a = item; 
    } 
} 
public class Z extends X { 
    public void insert(Object item) { 
    /* nothing */ 
    } 
} 

// method signature : public X someSecretBlackBoxMethod() 
X x = someSecretBlackBoxMethod(); 

現在,someSecretBlackBoxMethod方法返回擴展X一類的具體實例,對不對?那麼,哪一個呢,YZ

那麼,編譯器也不知道。這就是編譯器無法解析x.a的原因。不過,如果你丟在Y(即((Y)x).a),那麼編譯器知道x應該Y一個實例,因此,瞭解屬性。現在,在運行時,如果x而不是一個Y的實例,那麼你得到了ClassCastException