JB *_*zet 13 java constructor final jls
考虑这两个类:
public abstract class Bar {
protected Bar() {
System.out.println(getValue());
}
protected abstract int getValue();
}
public class Foo extends Bar {
private final int i = 20;
public Foo() {
}
@Override
protected int getValue() {
return i;
}
public static void main(String[] args) {
new Foo();
}
}
Run Code Online (Sandbox Code Playgroud)
如果我执行Foo,则输出为20.
如果我使字段非final,或者我在Foo构造函数中初始化它,则输出为0.
我的问题是:在最终字段的情况下,初始化顺序是什么?JLS中描述了这种行为?
我希望找到最终的领域一些特殊的规则在这里,但除非我错过了什么,没有.
请注意,我知道我永远不应该从构造函数中调用可覆盖的方法.这不是问题的关键.
Jes*_*per 17
您的final int i成员变量是常量变量:4.12.4.final变量
原始类型或类型的变量
String,即final,用一个编译时间常量表达式(§15.28)初始化,被称为恒定变量.
这会对事物初始化的顺序产生影响,如 12.4.2所述.详细的初始化程序.
以“字节码”的方式带您了解它的外观。
您应该已经意识到,构造函数中的第一个实际指令必须是调用super(无论是否带参数)。
当父构造函数完成并且超级“对象”完全构造完毕时,该超级指令返回。因此,当您构建时,Foo会发生以下情况(按顺序):
// constant fields are initialized by this point
Object.construction // constructor call of Object, done by Bar
Bar.construction // aka: Foo.super()
callinterface getValue() // from Bar constructor
// this call is delegated to Foo, since that's the actual type responsible
// and i is returned to be printed
Foo.construction
Run Code Online (Sandbox Code Playgroud)
如果您要在构造函数中初始化它,那么这将在“现在”发生,在getValue()已经被调用之后。
| 归档时间: |
|
| 查看次数: |
1090 次 |
| 最近记录: |