2014-03-13 108 views
3

我是新來的Java,現在我得到了方法重寫一個問題:Java的替代混亂

public class maintest { 
    public static void main(String[] args) { 
     new Zi(); 
    } 
} 

public class Fu { 

    public Fu() { 
     show(); 
    } 
    public void show() { 
     System.out.println("This is from Fu show"); 
    } 
} 

public class Zi extends Fu { 
    public Zi() { 
     show(); 
     super.show(); 
    } 

    public void show() { 
     System.out.println("This is from zi show"); 
    } 
} 

當我運行這個程序,輸出是:

This is from zi show 
This is from zi show 
This is from Fu show 

誰能給我爲什麼第一輸出線是

This is from zi show 

而不是

一些簡單的理解的解釋
This is from Fu show 

換個角度來說,爲什麼超類中的show方法是隱藏的?

+1

你重寫'Zi'中的方法,所以調用'show()'的'Zi'對象總是調用'Zi'版本。 – dlev

+0

@dlev我不太明白,當super()被調用時,爲什麼它會在Zi的上下文中運行?你可以在內存位置的角度顯示它嗎? (如JVM結構) – Kuan

+0

如果您的Fu構造函數中沒有顯示,您應該看看您的期望。 –

回答

4

在你的構造你這樣做,

public Zi() { 
    super(); // <-- you didn't have this, so the compiler added it. 
      // your Fu class then calls Zi's show. 
      // Why? Because Zi has a method named show that override Fu's 
      // show method. So the Fu constructor (when it calls show()) gets the 
      // show implementation in Zi. 
    show(); // <-- first explicit show call (but the second "This is from zi show") 
    super.show(); // <-- then call the Fu.show() 
} 
+0

爲什麼super()中的關鍵字「this」是指Zi? – Kuan

+0

不是關鍵詞「this」...但有一個隱式調用super()構造函數 - 我添加它(super())。 –

+0

@Kuan Java的工作原理就是如此。在任何構造函數中,Java都會在開始時_implicitly_調用超類構造函數。回答者向你展示了它的外觀,因此你可以看到爲什麼你的輸出有三條線,而不是你預期的兩條線。 –

0

超類Fu構造函數調用您已在子類中已經overrided的方法show,所以overrided方法被調用。

+0

感謝您的解釋,但如果我想在super()中使用Fu的演出怎麼辦?我怎樣才能做到這一點? – Kuan

+0

只是你不能。但在子類方法中,如果調用'super.show()'那麼超級方法將被調用 –

+0

那麼,這是否意味着:一個好的模式永遠不會超越一個在超類的構造函數中的方法? – Kuan

0

讓我們考慮輸出的每一行。

第一行第一次調用來show()Fu構造,這之前被隱式調用調用的Zi構造。

第二行是從show()裏面的構造函數Zi

第三行來自super.show(),它明確調用父類Fu上的show()方法。

+0

爲什麼第一個節目()是在Zi的背景下而不是Fu?如果在Fu的節目中第一個節目,爲什麼這是指Zi? – Kuan

+0

當一個方法在一個子類中被覆蓋並且我們正在構造一個子類的實例時,除非在上面的例子中明確地重寫(比如'super'),否則對該方法的所有調用都將轉到子類的方法。它不是關於「上下文」,而是關於正在構建的對象的類型。這裏我們構造了一個'Zi'類型的對象,所以儘管'Fu'的構造函數調用了show(),但它仍然調用了'Zi'的'show'。 – merlin2011

+0

感謝您的解釋,但如果我想在super()中使用Fu的演出怎麼辦?我怎樣才能做到這一點? – Kuan

0

當您在Fu構造函數中調用show時,現在將調用Zi的真實對象的顯示方法。

基本上在內存中只有一個對象是Fu和Zi。該對象的show方法最深(在繼承樹中)被覆蓋的版本,在這種情況下是Zi的表演。

+0

你能否給我一些關於這個方法如何顯示存儲在memeory中的Fu和Zi的細節? – Kuan

+0

我補充一點。 –

+0

感謝您的幫助。 – Kuan

0

您已經重寫了Zi.show的Fu.show。這意味着即使在父類中調用show()時,也會調用子類方法。

在一個真實的例子,

你父親(家長)的公司。你(孩子)從他那裏繼承了這一點。你指定一個新的接待員(由孩子覆蓋父母的接待員)。現在所有來電的父親的公司都會收到你的接待員。

希望這是明確的。

+0

感謝您的解釋,我想我可能需要閱讀更多的瞭解這一點。 – Kuan

1

new Zi()被調用,

它調用其構造

Zi() { 
     a. super(); //the Java compiler automatically inserts a call to the no- argument constructor of the superclass 
     b. show(); 
     c.super.show(); 
    } 

一個。當調用super()類構造函數時。它發現show()方法..(由於對象引用是從子類,因此紫的show()返回「這是從子節目」

public Fu() { 
      System.out.println(this.getClass().getName()); //add this.. it will return   **"Zi"** 
      show(); // So this will return Zi's show(), due to refrence of Zi's object, when called by the sub class constructor. 
    } 

show() - 將返回「這是紫秀」

℃。super.show() - 將返回超級的show()

+0

感謝您的解釋,但是如果我想在super()中使用Fu's show?我怎樣才能做到這一點? – Kuan

+0

由於對象引用是super()中Zi的對象,因此它總是調用zi的show()方法,以顯示Fu的show()方法,因此您必須顯式地將對象的類型引用定義爲Fu的類型。所以它會援引.. – Rakesh

+0

請學會格式化您的文章! – sakura

0

您可以檢查什麼是你的程序的流程。檢查System.err.println()方法的輸出。

​​

的輸出將是:

This is from zi show 
This is from zi show 
This is from Fu show 
Fu Constructor 0 
Zi show 1 
Zi Constructor 2 
Zi show 3 
Fu show 4 

輸出的從System.out.println()System.err.println()序列可以變化。

上述輸出告知第一Fu類的對象的情況下(如ZiextendsFu)然後show()方法和Zi類的constructor稱爲然後Fu類的由於super.show()show()方法被調用。哪一個是你的輸出。