构造对象实例时创建的输出是什么

时间:2014-10-24 01:59:46

标签: java

假设以下代码运行且没有错误:

enter image description here

并假设在其他课程中我们有一个主要方法:A var1 = new C();

我得到了这两个问题,我回答错了:

1)通过构建C实例来创建什么输出?

我对此的回答是 some ,我认为这是因为它说new C();,所以它创建了一个新的C对象,并在该类的构造函数中打印一些。但我错了,正确答案就是这里的一些。这对我来说没有意义,我也不知道这是怎么可能的。

2)如果使用方法调用((B) var1).report(),则调用哪个方法。

我对此的答案是B班的方法报告。我认为这是正确的答案,因为var1是用B转换的,所以我假设它将使用B类中的方法。但我也错了。正确答案是C类中的方法。这对我来说也没有意义。

这非常令人困惑,我真的不知道如何得到这些答案。如果有人能够向我解释究竟发生了什么,以及他们如何得到那些真正值得赞赏的答案。

3 个答案:

答案 0 :(得分:5)

回答1)。部分正确的是,C的构造函数将被调用,但不要忘记子对象将始终在其父对象上调用构造函数。如果子类没有指定要调用的构造函数,那么将使用no-args构造函数。

所以在C的构造函数中,编译器添加了对super()的调用,它调用了B上的构造函数,再一次编译器添加了对super()的调用,调用了A上的构造函数。所以整个链最终成为A() - > B() - > C()。

回答2)。即使将arg1强制转换为B,它仍然是C的实例。因此,多态将导致对C上的report()方法的调用。

如果将A重命名为Animal,B将重命名为Mammal,将C重命名为Dog,则可能更容易想象。所以你可以将一个狗的实例称为动物或哺乳动物而且它是正确的,但它并没有改变它仍然是狗的事实。希望有所帮助。

答案 1 :(得分:1)

他们从Java Language Specification8.8.7. Constructor Body部分得到了答案:

  

如果构造函数体不以显式构造函数开头   调用和声明的构造函数不是   原始类Object,然后构造函数体隐式开始   使用超类构造函数调用“super();”,调用   它的直接超类的构造函数,不带参数。

部分8.4.8.1. Overriding (by Instance Methods)

class Point {
    int x = 0, y = 0;
    void move(int dx, int dy) { x += dx; y += dy; }
}
class SlowPoint extends Point {
    int xLimit, yLimit;
    void move(int dx, int dy) {
        super.move(limit(dx, xLimit), limit(dy, yLimit));
    }
    static int limit(int d, int limit) {
        return d > limit ? limit : d < -limit ? -limit : d;
    }
}
  

这里,SlowPoint类使用自己的移动方法覆盖类Point的方法移动的声明,这限制了距离   该点可以在每次调用方法时移动。当。。。的时候   对于SlowPoint类的实例调用move方法   类SlowPoint中的重写定义将始终被调用,甚至   如果对SlowPoint对象的引用是从变量中获取的   其类型为Point

答案 2 :(得分:0)

每个构造函数(ctor)做的第一件事,无论是否显式写入,都是调用超类ctor(如果未明确指定,则调用没有参数的那个)。因此C的ctor调用B,它调用A,它调用Object的ctor(A的超类,即使A未明确声明为“A extends Object”)。 Object ctor不打印任何内容。它返回A,打印“one”,然后返回到B,打印“here”,然后返回到C,打印出“some”。

one
here
some

在调用report()的情况下,对B的强制转换无关紧要。 Java中的方法是根据对象的实际运行时类型调度的,在这种情况下,var1对象的类型为C。因此,当调用该方法时,JVM会查看实际对象并找到C.report()方法。那就是那个被派遣的人。

对象的编译时类型是B,如果决定在编译时调用哪个方法,那么它将选择A.report()(因为{{1}在report())中没有重写方法,但是在已知对象的实际类型时,可以在运行时找到该方法。

(重载方法的哪个重载决定(具有相同名称但参数不同的两个方法)在编译时决定,但重写方法是在运行时选择。有些语言在运行时决定重载,但Java不是其中之一。)

相关问题