为什么这个继承示例输出“y”?

问题描述 投票:0回答:3

MySuper
类是父类,由
MySub
类扩展。我正在创建对象
MySub mySub = new MySub()
。我以为输出会是“y”,但是当我尝试运行代码时,它显示null

class MySuper {
    String strl = "x";

    public MySuper() {
        myMethod();
    }

    void myMethod() {
        System.out.print(strl);
    }
}

class MySub extends MySuper {
    String str2 = "y";

    void myMethod() {
        System.out.print(str2);
    }

    public static void main(String[] args) {

        MySub mySub = new MySub();
    }
}   
java oop inheritance polymorphism dispatch
3个回答
2
投票

MySub
使用的隐式构造函数如下所示:

class MySub extends MySuper {

  String str2;

  MySub() {
    super();
    str2 = "y";
  }

  // rest omitted for brevity
}

虽然内联字段初始化在技术上已移至构造函数中,但了解其本身并不一定重要。重要的部分是在初始化子类的字段之前调用超级构造函数。因此,当超级构造函数调用被子类重写的 myMethod() 方法时,

str2
字段尚未被分配非默认值。这会导致您的代码打印出来
null
这就是为什么你应该避免在构造函数中调用可重写的方法。


1
投票

在你的例子中。当您使用默认构造函数实例化

MySub

实例时,这会隐式执行对超类构造函数的调用。在超类的构造函数中,有一个对

myMethod()
的调用,它在
MySuper
中声明并在
MySub
中重写。
现在,即使 

myMethod

是从超类的构造函数中调用的,这可能会让我们误以为正在调用

myMethod
的超类版本,但这并不是实际发生的情况。
执行所有这些调用的实例仍然是一个 

MySub

实例;因此,Java 调用的

myMethod
实现是最接近
MySub
的实现,即
myMethod
MySub
覆盖。
那么,如果在这种情况下,超类构造函数中调用的 

myMethod

版本是被

MySub
覆盖的版本,为什么它不打印
str2
值呢?这是因为,虽然方法调用是动态调度的,但字段是静态调度的。在Java中,只有方法可以覆盖其基类的方法。子类的字段只能影子基类的字段(具有相同的名称)。因此,Java 在编译时已经知道哪些字段正在被使用,并且“仅”在运行时知道正在调用哪些方法实现。这意味着当您在子类中使用字段时,您可以确保您使用的字段始终是您所引用的字段。
回到你的例子,由于 myMethod 是从超类的构造函数中调用的,此时我们仍在初始化父对象,子类的字段尚未初始化,它们仍然包含默认值(引用的默认值为 null)。因此,在动态调度的 

myMethod

中,我们正在打印静态调度的

str2
的值,该值仍为 null,因为子类初始化尚未发生。
    

小错误:

-1
投票

由于扩展了 MySuper 类,因此出现

    null
  1. 输出,并且不需要扩展 MySuper 类,因为可以在包中的任何位置创建默认类对象,而无需扩展它。 创建对象 mySub 后,您尚未调用方法
  2. myMethod()
  3. 。这就是为什么它没有将输出打印为 y 解决方案
  4. : 尝试下面的代码,它运行顺利。

class MySuper { String strl = "x"; public MySuper() { myMethod(); } void myMethod() { System.out.print(strl); } } // class MySub extends MySuper { class MySub { String str2 = "y"; void myMethod() { System.out.print(str2); } public static void main(String[] args) { MySub mySub = new MySub(); // extra line added mySub.myMethod(); MySuper ms=new MySuper(); } }

© www.soinside.com 2019 - 2024. All rights reserved.