6

我对重写构造函数感到非常困惑。构造函数不能被覆盖是我在谷歌搜索时得到的结果我的问题是

public class constructorOverridden {

    public static void main(String args[]) {
        Sub sub = new Sub();
        sub.test();
    }
}

class Super {
    Super() {
        System.out.println("In Super constructor");
        test();
    }

    void test() {
        System.out.println("In Super.test()");
    }
}

class Sub extends Super {
    Sub() {
        System.out.println("In Sub constructor");
    }

    void test() { // overrides test() in Super
        System.out.println("In Sub.test()");
    }
}

当我运行它时,我得到的结果为

In Super constructor
In Sub.test()
In Sub constructor
In Sub.test()

请注意子类中的测试方法已执行。是否表明超类构造函数已被覆盖。是否正确?

4

5 回答 5

20

构造函数不是多态的——你根本不会覆盖它们。您在子类中创建的构造函数,并且每个子类构造函数都必须(可能间接地)链接到超类构造函数。如果您没有显式链接到构造函数,则会在子类构造函数主体的开头插入对无参数超类构造函数的隐式调用。

现在就覆盖方法而言- 一个对象从一开始就是它的“最终类型”,包括在执行超类构造函数时。因此,如果您getClass()Super构造函数代码中打印,您仍然会Sub在输出中看到。其结果是调用了被覆盖的方法(即Sub.test),即使Sub尚未执行构造函数。

这基本上是一个坏主意,您几乎应该始终避免在构造函数中调用可能被覆盖的方法 - 或者非常清楚地记录这种情况(以便子类代码知道它不能依赖已被适当初始化等)。

于 2013-02-01T09:42:45.317 回答
4

您不能覆盖构造函数,因为构造函数是由它构造的类的名称调用的。如何使用相同的构造函数创建一些不同的类?此外,子类不会从其父类继承构造函数。

如果父构造函数做了一些重要的初始化,可以使用 super 从子构造函数调用它:

class Err extends Throwable {
   Err(String message) {
       super(message); // Call the constructor of Throwable.
        ..

父类构造函数也总是被调用。如果您自己不调用任何构造函数,则在进入派生类的构造函数之前会自动调用不带参数的构造函数。如果父级没有无参数构造函数并且您没有调用任何构造函数,则会报告编译时错误。

于 2013-02-01T09:44:51.550 回答
3

构造函数的第一行隐式调用是对Super(). 这就是你得到这些结果的原因。

于 2013-02-01T09:41:53.797 回答
3

这是正确的。实例化子类时,首先调用超类构造函数,然后调用层次结构中的每个后续构造函数。

在上面的示例中,超类构造函数调用了一个被覆盖的方法 ( test())。这可行,但有潜在危险,因为尚未调用子类构造函数,并且您的子类还没有完全初始化。出于这个原因,在构造函数中调用被覆盖(或可覆盖)的方法并不是一个好的做法。

于 2013-02-01T09:42:17.603 回答
2

它不是覆盖超类构造函数,并且构造函数不能被覆盖它可以被重载。

当您创建子类对象时,将首先实例化超类,然后再实例化子类。它就像Child 不能没有 parent 存在

编译器会自动从子类构造函数调用超类构造函数。

Sub() {
    super();
    System.out.println("In Sub constructor");
}
于 2013-02-01T09:44:17.460 回答