2014-03-13 65 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()方法被调用。哪一个是你的输出。