[英]JAVA inheritance constructor order of call
当我运行以下程序时
public class Example {
static class A {
A()
{
f();
}
public void f(){
System.out.println("A ctor");
}
}
static class B extends A {
B()
{
f();
}
public void f() {
System.out.println("B ctor");
}
}
public static void main(String[] args) {
B b = new B();
b.f();
A a = new A();
a.f();
}
}
我期待以下
A ctor
B ctor
B ctor
A ctor
A ctor
但相反我得到
B ctor
B ctor
B ctor
A ctor
A ctor
我很困惑为什么会这样。 对B
的构造函数的第一次调用应该调用Af()
(通过对A
的构造函数的自动调用)但看起来像它调用Bf()
为什么?
当您编译B.java
时,编译器会插入一些代码。 当您键入时。
B() {
f();
}
如果你反转 Java 字节码,你会清楚地看到如下指令
B() {
super();
f();
}
但是,虽然这可以解释继承问题,但您的代码存在很大问题。
在未构造的 class 上调用函数是不安全的。
所以在A()
f()
) 是不安全的。 这是因为在 A() 的构造函数完成之前, A()
A()
还没有完全构造。 同样,出于同样的原因,在B()
f()
) 也是不安全的。
如果您将f()
转换为不使用this
引用的 static 成员,那么您将拥有安全代码; 但是,您不会在f()
调用中获得多态性。
请记住, f()
调用是对 object 的调用。 在连接对象的动态方法的过程中,对f()
的调用可能会引用A
或B's
实现,并且在构造时,并不总是可能知道应该调用哪一个,因为A()
的构造函数在B()
构造函数内部和外部都以相同的方式调用。
既然已经说明了一般规则,以下是例外情况:
如果g()
是最终成员 function,您可以在构造函数中安全地调用一些 function g()
,它指的是在 ZA2F2ED4F8EBC2CBB4C21A29DC40AB61 级别中已正确分配和最终的变量。
您可以安全地在父 class 中调用一些 function h()
,如果h()
仅写入父 class 有效私有的变异变量。
如果 j( j()
使用的所有变量都具有合理的赋值,您可以在父 class 中调用一些 function j()
,但如果变量因突变而泄漏到较低的子类,您可能看不到所需的结果。
基本上,如果您对如何构造类有足够的了解,则可以编写代码以使用构造顺序,因为您正在围绕失败案例编写函数。 前两种方法被认为是“好的设计”,最后一种方法被认为是“糟糕的设计,但我们会在它工作的时候去做”质量代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.