簡體   English   中英

解釋變量隱藏在這個Java代碼中是如何工作的

[英]Explain how variable hiding is working in this Java code

考慮下面的代碼

class A
{
    int x = 5;
    void foo()
    {
        System.out.println(this.x);
    }
}
class B extends A
{
    int x = 6;
    // some extra stuff
}
class C
{
    public static void main(String args[])
    {
         B b = new B();
         System.out.println(b.x);
         System.out.println(((A)b).x);
         b.foo();
    }
 }  

該計划的輸出是

6
5
5

我理解前兩個但是無法理解最后一個。 b.foo()如何打印5.B類將繼承foo方法。 但它不應該打印bx會打印什么? 到底發生了什么?

是的, B類繼承了foo方法。 但是B的變量x隱藏了Ax ; 它不會取代它。

這是一個范圍問題。 Afoo方法只能看到范圍內的變量。 范圍中唯一的變量是A的實例變量x

foo方法在B繼承但未被覆蓋。 如果您使用相同的確切代碼顯式覆蓋foo

class B extends A
{
    int x = 6;

    @Override
    void foo()
    {
        System.out.println(this.x);
    }
}

然后該變量時提到了,這將是在范圍this.xBx ,和6將被打印。 雖然方法的文本是相同的,但由於范圍的原因,引用是不同的。

順便提一下,如果你真的想在B類中引用Ax ,你可以使用super.x

字段在Java和具有相同字段名稱的子類中不能覆蓋父類陰影“僅”父類的字段。
所以this.x指的是當前類中定義的xA
結果: 5

更確切地說: foo()方法由B子類繼承,但它並不意味着繼承方法的行為將因引用的實例字段而改變,因為所述字段不可覆蓋:引用的this.x表達式foo()方法中的Ax字段繼續引用Ax

這與之前的兩個陳述完全相同:

 B b = new B();
 System.out.println(b.x); // refers B.x -> 6
 System.out.println(((A)b).x); // refers A.x -> 5
 b.foo(); // refers under the hood A.x -> 5

rgettman的非常好的答案顯示了如何克服隱藏在子類中的字段。
克服隱藏的替代方法依賴於使實例字段為private (建議使用)並提供返回值的方法。
通過這種方式,您可以從覆蓋機制中受益,並且字段隱藏不再是類的客戶端的問題:

class A
{
    private int x = 5;

    int getX(){
        return x;
    }

    void foo()
    {
        System.out.println(this.getX());
    }
}
class B extends A
{
    private int x = 6;

    int getX(){
        return x;
    }
}

嗯,這是因為靜態綁定。

1)Java中的靜態綁定在編譯時發生,而動態綁定在運行時發生。

2)私有方法,最終方法和靜態方法和變量使用靜態綁定並由編譯器綁定,而虛擬方法在運行時基於運行時對象綁定。

3)靜態綁定使用Type(Java中的類)信息進行綁定,而動態綁定使用Object來解析綁定。

4)使用靜態綁定綁定重載方法,而在運行時使用動態綁定綁定重寫方法。

JAVA中 ,可以覆蓋方法,而變量則不能。 因此,由於您的方法foo未在B被覆蓋,因此它從A獲取成員變量。

你打電話的時候

b.foo(); 

它檢查B是否覆蓋了方法foo() ,它沒有。 然后它向一個級別向上看,超類A並調用該方法。

然后你調用了Afoo()版本然后打印出來

this.x

現在, A看不到Bx版本。


為了解決這個問題,你必須覆蓋B的方法

class B extends A
{
    int x = 6;

    @Override
    void foo()
    {
        System.out.println(this.x);
    }

}

現在,打電話

b.foo();

將調用Bfoo()版本,您將獲得預期的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM