java初始化字段变量
public class Foo {
private int var;
public Foo() {
var = 10;
}
}
在这个代码段中,var
会先被分配一个默认值,然后再被重新分配到10,还是直接分配到10而不分配默认值
有点小问题,但我很好奇
你可以在下面搜索框中键入要查询的问题!
public class Foo {
private int var;
public Foo() {
var = 10;
}
}
在这个代码段中,var
会先被分配一个默认值,然后再被重新分配到10,还是直接分配到10而不分配默认值
有点小问题,但我很好奇
# 1 楼答案
它将首先被赋予默认值。特别是,如果Foo是从Bar派生的,并且Bar的构造函数可以以某种方式获取var的值(例如,通过在Bar中声明并在Foo中重写的虚拟方法),那么即使变量是final,该默认值也是可见的。例如:
请注意,即使在声明点初始化字段,也会发生此仍然:
在这方面,Java不同于C#。在C#中,在调用基构造函数之前
var
将被赋值为10# 2 楼答案
指定默认值意味着在指定默认值之前它有一个值。对象在创建时具有默认值,但未指定该值
如果查看字节码,唯一的代码是分配新值
# 3 楼答案
如果查看
Foo.class
的反编译字节码,您将注意到以下内容:如果您编写以下内容:
字节码将是:
下一个示例显示,访问变量仍然不会导致任何值的赋值:
此代码将打印
0
,因为操作码8处的getField Foo.var
会将“0”推送到操作数堆栈上:# 4 楼答案
语言规范规定:
然后调用构造函数
# 5 楼答案
在调用构造函数之前,未初始化的字段将始终被分配默认值,因为运行时将在调用构造函数之前将对象的内存分配归零。它必须这样做,因为它不知道构造函数可能提前做什么,并且因为派生类可能存在于其他JAR/类路径中,并获取值(如果受保护)或调用使用该字段的方法,然后再由构造函数初始化
这是独立于编译器执行的,因此这不是编译器可以优化的,编译器甚至不能控制它
# 6 楼答案
根据spec:(第4.2.15节)
前0名
然后是10
如果您首先在构造函数中读取它,您将得到0