对Java中的继承方法和字段感到困惑

时间:2018-09-27 04:21:03

标签: java class oop inheritance

我试图对子类如何访问超类的方法和字段进行一些研究。 当我读到一篇关于stackoverflow的文章,解释了继承“真正”如何工作时,我很困惑地看到我的输出。我读的帖子是:What really happens on inheritance in Java?

在阅读了这篇文章之后,这是我对继承的理解,请您纠正是否正确:

  • 方法和字段不会复制到子类,而是从超类对象调用,除非在子类中重写。我已经确认使用 javap 命令不会将方法和字段复制到子类中。
  • 在子类中调用方法时,它将在运行时在子类对象中查找该方法(可能是覆盖的方法),如果找不到该方法,则它将在层次结构中向上查找以在超类对象中找到它,然后调用它是从超类对象开始的。
  • 由于方法和字段没有复制到Subclass,而是从Superclass对象调用,因此Subclass构造函数调用super();。隐式地确保有一个Superclass对象可用于从中调用继承的方法。

应用我刚刚写下的逻辑,我遇到了一些奇怪的输出。在下面的示例中,我有A类( Superclass )和B类( Subclass )。我从Main方法接收到B作为输出,但是却期望A作为输出。

A类:

public class A {
    public void getTheClass() {
        System.out.println(getClass().getSimpleName());
    }
}

B级:

public class B extends A {
    public B() {
        getTheClass();
    }

}

主要班级:

public class Main {
    public static void main(String[] args) {
        B b = new B();
    }
}

我之所以期望A作为输出,是因为(根据前面描述的逻辑) getTheClass()方法将从超类对象(A)作为子类对象(B)调用)没有名为getTheClass()的方法。 Subclass对象没有此方法,因为根据我的理解,方法和字段不会复制到Subclasses。

如果子类不具有此方法,则它将在层次结构中向上搜索以查找具有该方法的对象并从那里调用它,在这种情况下,该对象将是超类对象(A)。因此,如果从超类对象(A)调用 getTheClass()方法,那么该对象的类不是A类而不是B类吗?在这种情况下,为什么不输出A而是输出B?如果我打印出关键字 this ,我会得到同样令人困惑的结果。

1 个答案:

答案 0 :(得分:2)

  

因为当在子类对象中找不到被调用的方法时,它会在层次结构中向上移动,因此子类构造函数将调用super();隐式地确保有一个超类对象可用于从中调用继承的方法。

在创建对象本身时将调用构造函数(在子对象和父对象中),而不是在对象上调用方法时调用(因为您需要完全构造的对象来调用对象上的方法)。

之所以看不到打印的类名称为A,是因为getClass()方法返回了对象的 runtime 类型(即{{1 }})

来自javadoc,(强调我的

  

返回此对象的运行时类。返回的Class对象是被表示的类的静态同步方法锁定的对象。

参考:

What is a "runtime class" in Java?