【问题标题】:Confused about inheriting methods and fields in Java对继承Java中的方法和字段感到困惑
【发布时间】:2018-09-27 04:21:03
【问题描述】:

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

看完这篇文章,这是我对继承的理解,如有错误请大家指正:

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

应用我刚刚写下的逻辑,我遇到了一些奇怪的输出。在下面的示例中,我有 A 类(超类)和 B 类(子类)。我从 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,我会得到同样令人困惑的结果。

【问题讨论】:

  • getClass() 返回对象的运行时类。
  • 补充其他人所说的,getClass() 本身继承自java 中的Object 基类。所以根据你的推理 getClass 不会返回 A 但会返回 Object.
  • 你已经构造了 B 类 [ new B() ],A 类只是将它的字段和方法分享给它的孩子。要让它输出类 A,你需要构造 A。

标签: java class oop inheritance


【解决方案1】:

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

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

你看不到打印出来的类名是A的原因是getClass()方法返回了对象的runtime类型(也就是B

来自javadoc,(强调我的

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

参考:

What is a "runtime class" in Java?

【讨论】:

  • 是的,我的错,我在那里打错了。你能解释一下这个“对象的运行时类型”是如何工作的,并导致我的代码不输出A吗?我不太明白运行时类型和我现在理解的区别。
  • 当您拥有A ob = new B()B ob = new B() 时,您将拥有B 类型的对象(它也可以分配给A 类型的引用,因为所有Bs 都是As)。这里的运行时类型是实际创建的对象,这里是B。(还要注意创建BA的构造函数将被调用。您可以通过在@中编写默认构造函数来验证这一点987654336@ 和 A 查看它们的调用顺序)。
  • 但在我的示例中,我正在创建一个对象 A(带有隐式超级调用)和一个对象 B。在运行时,因为 getTheClass() 未在对象 B 中定义,它使用 getTheClass( ) 来自对象 A。因此,如果它会执行 A.getTheClass(),那么在这种情况下,运行时类不是 A 吗?
  • 没有。您没有创建A 类型的对象,而且运行时类型是B。想一想——如果运行时类型是A,您如何访问B 上的字段和方法(如果该对象不是B 类型)。只有A中的方法被调用,但实际类型是B
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 2019-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
相关资源
最近更新 更多