Java 当对象的所有字段都设置为默认值时,为什么实例常量有一个值?
代码如下:Java 当对象的所有字段都设置为默认值时,为什么实例常量有一个值?,java,polymorphism,Java,Polymorphism,代码如下: public class Main { public static void main(String[] args) { new B(); } } class A { A() { System.out.println("A constructor before"); action(); System.out.println("A constructor after&
public class Main {
public static void main(String[] args) {
new B();
}
}
class A {
A() {
System.out.println("A constructor before");
action();
System.out.println("A constructor after");
}
protected void action() {
System.out.println("Never called");
}
}
class B extends A {
private final int finalField = 42;
private int field = 99;
B() {
System.out.println("B constructor");
action();
}
public void action() {
System.out.println("B action, finalField=" + finalField + ", field=" + field);
}
}
结果是:
A constructor before
B action, finalField=42, field=0
A constructor after
B constructor
B action, finalField=42, field=99
我被这句话弄糊涂了:
B action, finalField=42, field=0
对象B没有完全初始化,当我们从超类构造函数调用方法“action”时,变量“field”有一个默认值,但最终变量“finalField”已经有值42
“finalField”是什么时候初始化的?当最后一个字段用a初始化时,它被称为a: 这意味着字符串
"B action, finalField=" + finalField + ", field="
本身是一个常量表达式,其值在编译时确定。如果检查编译后的类文件,实际上会在常量池部分找到字符串B action,finalField=42,field=
通常,当使用常量变量字段时,必须在编译时将其替换为其值。要在运行时引用该字段,请执行以下操作:
A
构造函数返回之后和B
构造函数启动之前,字段初始值设定项仍会在您预期的时间运行。观察未初始化的值很棘手,因为编译器将变量的使用内联起来,但您可以通过反射来访问字段的值:
public void action() {
try {
System.out.println("B action, finalField="
+ getClass().getDeclaredField("finalField").get(this)
+ ", field=" + field);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
输出:
A constructor before
B action, finalField=0, field=0
A constructor after
B constructor
B action, finalField=42, field=99
在java中有两种类型的流
- 从父级到子级的静态成员标识
- 从父级到子级执行静态变量赋值和静态块
- 独子类main的执行
- 无论何时执行Java类,都将首先执行静态控制流
- 从父级到子级的实例成员标识
- 仅在父级中执行实例变量分配和实例块 阶级
- 父类构造函数的执行
- 在子类中执行实例变量赋值和实例块
- 子类构造函数的执行
图灵的链接有答案,但格式清晰,这是一个很好的问题。dupe对我来说似乎不正确,它似乎无法解释
字段
和最终字段
的初始化顺序似乎不同。(查看字节码,在调用A的构造函数后,field和finalField都在B的构造函数中初始化,所以这里发生了其他事情)。投票表示感谢!我通过link阅读了这篇文章,但我仍然有一个问题,为什么final变量没有设置为默认值(在本例中为0)。看看字节码,看看普通字段和final字段之间有什么不同。谢谢。我需要了解更多。理解“final”有问题吗 case@RomanFrolov对于最后一种情况,我认为这很简单。您只需要知道,在jvm开始执行程序之前,每个最终变量都是在编译时计算的。就是这样!我现在可以安心睡觉了:)
A constructor before
B action, finalField=0, field=0
A constructor after
B constructor
B action, finalField=42, field=99