我对Overriding Constructors非常困惑。构造函数不能被覆盖是我在谷歌搜索它时得到的结果我的问题是
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()
请注意子类中的测试方法已执行。它是否表示重写了Superclass构造函数。是否正确?
答案 0 :(得分:20)
构造函数不是多态的 - 你根本不会覆盖它们。您在子类中创建 new 构造函数,并且每个子类构造函数必须链接(可能是间接)到超类构造函数。如果没有显式链接到构造函数,则会在子类构造函数体的开头插入对无参数超类构造函数的隐式调用。
现在在重写方法方面 - 一个对象从一开始就是它的“最终类型”,包括执行超类构造函数时。因此,如果您在getClass()
构造函数代码中打印Super
,您仍会在输出中看到Sub
。即使Sub.test
构造函数尚未执行,也会调用被覆盖的方法(即Sub
)。
这基本上是一个坏主意,你应该几乎总是避免在构造函数中调用可能被覆盖的方法 - 或者非常清楚地 文档,以确保情况如此(以便子类代码知道它不能依赖已经适当初始化的变量等。)
答案 1 :(得分:4)
您无法覆盖构造函数,因为构造函数是由它构造的类的名称调用的。如何使用相同的构造函数创建一些不同的类?此外,子类不会从其父级继承构造函数。
如果父构造函数执行了一些重要的初始化,则可以使用super:
从子构造函数中调用它class Err extends Throwable {
Err(String message) {
super(message); // Call the constructor of Throwable.
..
也始终调用父类构造函数。如果您自己不调用any,则在输入派生类的构造函数之前会自动调用不带参数的构造函数。如果父级没有无参数构造函数而您没有调用any,则报告编译时错误。
答案 2 :(得分:3)
构造函数的第一个隐含行是对Super()
的调用。这就是你获得这些结果的原因。
答案 3 :(得分:3)
这是对的。实例化子类时,首先调用超类构造函数,然后调用层次结构中的每个连续构造函数。
在上面的示例中,超类构造函数调用重写方法(test()
)。这可行,但由于尚未调用子类构造函数,因此存在潜在危险,并且您的子类将不会完全初始化。因此,在构造函数中调用重写(或可重写)方法并不是一种好习惯。
答案 4 :(得分:2)
它不会覆盖超类构造函数,并且构造函数不能被覆盖它可以重载。
当您创建子类对象时,将首先实例化超类,然后将实例化子类。就像 Child一样,没有父母就不能存在。
编译器将自动从子类构造函数中调用超类构造函数。
Sub() {
super();
System.out.println("In Sub constructor");
}