[英]Initialization of final fields
有人可以向我解释此示例的行为:
package test;
public class Test {
static abstract class Parent{
public Parent() {
print();
}
public abstract void print();
}
static class Child extends Parent{
protected final int i= 10;
public Child() {
super();
}
public void print(){
System.out.println(i);
}
}
public static void main(String[] args) {
System.out.println("Test");
new Child();
}
}
此代码段的输出为10 。 但是,当我将变量i更改为任何对象(例如Integer)时,输出为null 。 但是,当我改变我的静态整数输出为10预期。
我认为,在调用任何方法(或构造函数)之前都要先初始化字段,但是这里这种方法仅适用于原始类型,而不适用于对象。
谢谢
拉迪姆
类的实例字段是在构造函数中的super()
调用之后直接初始化的,无论它们是否为最终值。 但是, super()
调用父级的类构造函数,该构造函数读取因此未初始化的字段的值。
上课的时候在运行时,这意味着一类的构造函数被调用(在之前之前静态字段initilized引用类的静态字段都被初始化super()
在类的构造函数调用)。
当字段类型为int时,为什么仍打印10的原因是,Java编译器可以在编译时内联最后字段的值。 在那种情况下,程序永远不会读取该字段的值,因为编译器优化了代码,使其看起来像System.out.println(10)
而不是System.out.println(i)
。 在这种情况下,Java编译器不会内联最后字段,但是,对于原始字段类型很可能这样做,而对于大多数对象类型则不太可能。
非静态成员:
new Child()
以此顺序触发构造函数链接Parent()-> Child()。
当父对象被实例化时,您正在调用print(),因为它持有子对象的引用,它将调用
public void print(){
System.out.println(i);
}
因为在这个阶段,孩子的启蒙还没有完成。 整数i
没有任何值,因此它将输出null
。
静态变量:
一旦引用/调用了相应的类, Static data member
被初始化,因此它将打印10
。
这是因为逻辑上,应该在Child
存在之前Parent
应该存在。
因此,首先调用Parent
的构造函数,在此期间, 不会初始化Child
任何字段。
因此,当您调用被 Child
覆盖的print()
时,将print()
i
的未初始化值。
在类加载期间发生的类初始化时进行初始化,因此它们将具有初始化的值
由于字段的最终性质,与变量不同,它在构造函数之前初始化。 因此,将打印该值。
当您声明final Integer i = 10
时会发生什么? 或者int i = 10
?
主代码应为
Child child = new Child();
child.print();
然后,如果使用int或Integer,则返回10;否则,返回10。
仅使用
new Child()
则此变量没有返回值,并且新实例被忽略。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.