最终字段初始化顺序 [英] Final fields initialization order
问题描述
这是一些在尚未初始化的类上调用静态方法A.f()的代码。
有人可以用JLS来解释这段代码的行为吗?
A类{
final static Object b = new B();
final static int S1 = 1;
final static Integer S2 = 2;
static void f(){
System.out.println(S1);
System.out.println(S2);
}
}
B类{
static {
A.f();
}
}
公共类App
{
public static void main(String [] args)
{
Af ();
}
}
输出:
1
null
1
2
af()
in App.main()
触发类的初始化 A
。
初始化所有常量变量。唯一的常量变量是 S1
,现在 1
。
然后,其他静态字段按文本顺序初始化。 b
是第一个字段,它触发类 B
的初始化,后者又调用 Af ()
。 S2
只是 null
因为它尚未初始化。 b
的初始化现已完成。最后但并非最不重要的是, S2
初始化为整数
对象 2
。
S2
不是常量变量,因为它不是原始类型 int
但引用类型 Integer
。 S2 = 2;
是的自动装箱速记,S2 = Integer.valueOf(2);
。
如果字段声明中的声明符具有变量初始值设定项,则声明符具有声明变量的赋值(第15.26节)的语义。 / p>
[...]
请注意
static
字段常量变量(§4.12.4)在其他static
字段(第12.4.2节)之前初始化。这也适用于接口(第9.3.1节)。即使是狡猾的程序,也不会观察到这些字段具有默认的初始值(§4.12.5)。
常量变量是
final
基本类型或类型的变量String
使用常量表达式初始化(第15.28节)。变量是否是常量变量可能对类初始化(第12.4.1节),二进制兼容性(第13.1节,第13.4.9节)和明确赋值(第16节(定义赋值))有影响。
常量表达式是一个表示基本类型值的表达式或
String
,它不会突然完成,只使用以下内容组成:
- 原始类型和文字类型的文字
字符串
[...]
对于每个类或接口C,都有一个唯一的初始化锁
LC
。从C到LC
的映射由Java虚拟机实现决定。初始化C的过程如下:
[...]
否则,记录当前线程正在进行C的
Class
对象的初始化,并释放LC
。
然后,初始化C的
static
字段,它们是常量变量( §4.12.4,§8.3.2,§9.3.1)。
[...]
- 接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,好像它们只是一个块。
程序中的每个变量在使用其值之前必须具有值:
每个类变量,实例变量或数组组件在创建时都会使用默认值进行初始化(§15.9,§15.10.2): / p>
[...]
- 对于所有参考类型(§4.3),默认值value是
null
。
Here is some code that calls static method A.f() on class that is not initialized yet. Can someone explain behavior of this code in terms of JLS?
class A {
final static Object b = new B();
final static int S1 = 1;
final static Integer S2 = 2;
static void f() {
System.out.println(S1);
System.out.println(S2);
}
}
class B {
static {
A.f();
}
}
public class App
{
public static void main( String[] args )
{
A.f();
}
}
Output:
1
null
1
2
A.f()
in App.main()
triggers initialization of class A
.
All constant variables are initialized. The only constant variable is S1
, which now is 1
.
Then, the other static fields are initialized in textual order. b
is the first field, which triggers initialization of class B
, which in turn calls A.f()
. S2
is simply null
because it is not initialized yet. Initialization of b
is now complete. Last but not least, S2
is initialized to the Integer
object 2
.
S2
is not a constant variable because it is not of the primitive type int
but of the reference type Integer
. S2 = 2;
is an auto-boxing shorthand for S2 = Integer.valueOf(2);
.
If a declarator in a field declaration has a variable initializer, then the declarator has the semantics of an assignment (§15.26) to the declared variable.
[…]
Note that
static
fields that are constant variables (§4.12.4) are initialized before otherstatic
fields (§12.4.2). This also applies in interfaces (§9.3.1). Such fields will never be observed to have their default initial values (§4.12.5), even by devious programs.
A constant variable is a
final
variable of primitive type or typeString
that is initialized with a constant expression (§15.28). Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9), and definite assignment (§16 (Definite Assignment)).
A constant expression is an expression denoting a value of primitive type or a
String
that does not complete abruptly and is composed using only the following:
- Literals of primitive type and literals of type
String
[…]
For each class or interface C, there is a unique initialization lock
LC
. The mapping from C toLC
is left to the discretion of the Java Virtual Machine implementation. The procedure for initializing C is then as follows:[…]
Otherwise, record the fact that initialization of the
Class
object for C is in progress by the current thread, and releaseLC
.Then, initialize the
static
fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).[…]
- Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
12.4.2. Detailed Initialization Procedure
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):
[…]
- For all reference types (§4.3), the default value is
null
.
4.12.5. Initial Values of Variables
这篇关于最终字段初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!