继承:return语句的意外输出

时间:2014-08-02 08:39:44

标签: java inheritance

我正在接受Java认证的练习测试,并得到了这个问题:

  

下面的代码会打印什么?

class Baap {

    public int h = 4;

    public int getH() {
        System.out.println("Baap    "+h);
        return h;
    }  
}  

class Beta extends Baap {

    public int h = 44;

    public int getH() {
        System.out.println("Beta    " + h);
        return h;
    } 

    public static void main(String[] args) {  
        Baap b = new Beta();  
        System.out.println(b.h + "    " + b.getH());  
        Beta bb = (Beta) b;  
        System.out.println(bb.h + "   " + bb.getH());  
    }  
}  

这是答案:
Beta 44 4 44
Beta 44 44 44

我的问题:为什么来自主类的 4 而不是来自子类的 44 ?难道它不会返回44吗?

我也没有看到任何被另一个变量影响的变量,该变量具有更接近范围的相同名称。

(对不起我的英文。我说法语。)

2 个答案:

答案 0 :(得分:2)

这是因为Beta.hBaap.h是不同的字段。在b.h中,调用Baap.h(即4)并调用bb.hBeta.h(即44)。区别在于b.getH()调用Beta.getH()(因为b为new Beta()),但正在阅读Baap.h字段,而bb.getH()则调用Beta.getH()

查看main()方法:

class Baap {  
    public int h = 4;  
    public int getH() { System.out.println("Baap    "+h); return h; }  
}  

class Beta extends Baap {
    public int h = 44;
    public int getH() { System.out.println("Beta    "+h); return h; }

    public static void main(String[] args) {
        Baap b = new Beta();
        System.out.println(b.h + "    " + b.getH());
        /* The string concatenation gets compiled to:
         * new StringBuffer().append(b.h).append("    ").append(b.getH()).toString();
         *                             \ This is Baap.h         \ This prints Beta 44 and returns 44 from Beta.h
         */
        // Printed "Beta 44" from b.getH().
        // Printed "4    44" from statements concatenation.
        Beta bb = (Beta) b;  
        System.out.println(bb.h + "   " + bb.getH());
        /* The string concatenation gets compiled to:
         * new StringBuffer().append(bb.h).append("    ").append(bb.getH()).toString();
         *                             \ This is Beta.h          \ This prints Beta 44 and returns 44 from Beta.h
         */
        // Printed "Beta 44" from b.getH().
        // Printed "44    44" from statements concatenation.
    }
}
  

Oracle JavaTM Tutorials - Inheritance开始写道:

     

您可以在子类中执行的操作

     
      
  • 可以直接使用继承的字段,就像任何其他字段一样。
  •   
  • 您可以在子类中声明一个与超类中的字段同名的字段,从而将其隐藏(不推荐)。
  •   
  • 您可以在子类中编写一个新实例方法,该方法与超类中的签名具有相同的签名,从而覆盖它。
  •   
  • 您可以在子类中声明不在超类中的新字段。
  •   

了解更多:

答案 1 :(得分:2)

因此,您的问题是b.h评估为4而不是44的原因:

    Baap b = new Beta();  
    System.out.println(b.h + "    " + b.getH());  
                       ^^^ why is this 4?

原因是Java中没有数据多态性。即使它们共享相同的名称,Baap.hBeta.h也是不相关的字段。

当编译器解析b.h时,它会查看b的静态(即编译时)类型,而不是其动态(即运行时)类型。

b的静态类型为Baap,因此b.h解析为Baap.h,即4