2

我有以下java代码。

class A {

        public void method1() {
            System.out.println("A 1");
            method2();
        }

        public void method2() {
            System.out.println("A 2");
        }

    }

    class B extends A {
        @Override
        public void method2() {
            System.out.println("B 2");
        }
    }

    public class Tester {
        public static void main(String[] args) {
            A a = new B();
            a.method1();
        }
    }

它打印

    A 1
    B 2
  • 当调用 a.method1() 时,运行时到底发生了什么?
  • 如何从父级调用派生方法?
  • 它是在查看对象和方法名称字符串并在运行时调用方法吗?
  • 它是默认调用 this.method2() 吗?
4

5 回答 5

3

由于该方法method1(...)从未被覆盖,因此 B 继承了 A method1(),并且它被调用就好像它是在 B 中定义的一样。

由于method1()调用method2()了 B 中定义的重写方法method2(),因此当使用 B 构造函数创建实例时。

如果您使用 A 构造函数创建另一个实例,您将不会获得 B 中定义的覆盖,而是获得A 中定义method2(...)的原始实例。method2(...)

于 2017-12-27T17:44:59.413 回答
0

当调用 a.method1() 时,运行时到底发生了什么?

调用 A 类的 method1()。

如何从父级调用派生方法?

由于您已经method2在 B 类中覆盖了该方法,因此该方法将在运行时被调用。

它是在查看对象和方法名称字符串并在运行时调用方法吗?

不要在这里混淆。当你写

 A a = new B();

如果 B 类中的方法被调用,则 B 类中的方法会被调用,否则 A 类中的方法会被调用。

它是默认调用 this.method2() 吗?

同样,它不是违约。如果你 ovveride 它会从 B 调用。如果你不 ovveride,它会从 A 调用

于 2017-12-27T17:44:40.663 回答
0

因为您的对象实际上B是继承自A. 在你B的类中,你正在覆盖 method2 这就是它调用的原因B.method2()

  A a = new B();

method2要从调用A,请使用:

  A a = new A();
于 2017-12-27T17:45:00.503 回答
0

当 B 类型的对象被初始化时,它是 B 类的一个实例,即使它被隐式地强制转换为 A 类型的对象。

因此,当您调用时,a.method1()因为method1()未在 B 类中定义,它会调用基类中定义的方法。然后当method2()被调用时,它被定义在 B 类中,并且由于对象是 B 类型,所以调用 B 类中的方法。

于 2017-12-27T17:56:35.880 回答
0

您已经创建了子类的对象和引用类型的对象。引用的类型为 Parent(向下转换)

当您在引用上调用任何方法时,将调用类型引用的方法。但是如果该方法在引用类型中不可用,它将从父(继承)调用。

在您的示例中,编译器检查对象 A 中的 method1 并在那里找到它。其次,当方法 2 被调用时,它是从当前对象(对象 B 而不是引用 A)调用的。

请注意,当您从 A 的引用调用 method2 时,它会被覆盖,它将从对象 A(父)调用方法,如果您从引用 B 调用它,它将从对象 B(子)调用。

这里要记住的关键点是引用和对象的区别。他们都是不同的实体。

*如果您从抽象类中调用具体方法,而该具体方法又调用了同一类的抽象方法,也会发生同样的情况。子类的实现方法将被调用。

于 2017-12-27T18:00:02.167 回答