[英]Final fields initialization order
Here is some code that calls static method Af() on class that is not initialized yet. 下面是一些在尚未初始化的类上调用静态方法Af()的代码。 Can someone explain behavior of this code in terms of JLS?
有人可以用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
Af()
in App.main()
triggers initialization of class A
. App.main()
Af()
触发A
类A
初始化。
All constant variables are initialized. 初始化所有常量变量。 The only constant variable is
S1
, which now is 1
. 唯一的常量变量是
S1
,现在为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 Af()
. b
是第一个字段,它触发B
类的初始化,而B
类又调用Af()
。 S2
is simply null
because it is not initialized yet. S2
只是null
因为它尚未初始化。 Initialization of b
is now complete. b
初始化现已完成。 Last but not least, S2
is initialized to the Integer
object 2
. 最后但并非最不重要的是,
S2
被初始化为Integer
对象2
。
S2
is not a constant variable because it is not of the primitive type int
but of the reference type Integer
. S2
不是常量变量,因为它不是基本类型int
而是引用类型Integer
。 S2 = 2;
is an auto-boxing shorthand for S2 = Integer.valueOf(2);
是
S2 = Integer.valueOf(2);
的自动拳击简写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.
如果字段声明中的声明符具有变量初始值设定项,则声明符具有声明变量的赋值(第15.26节)的语义。
[…]
[...]
Note that
static
fields that are constant variables (§4.12.4) are initialized before otherstatic
fields (§12.4.2).需要注意的是
static
字段是不变的变量(§4.12.4)先于其他初始化static
字段(§12.4.2)。 This also applies in interfaces (§9.3.1).这也适用于接口(第9.3.1节)。 Such fields will never be observed to have their default initial values (§4.12.5), even by devious programs.
即使是狡猾的程序,也永远不会观察到这些字段具有默认的初始值(§4.12.5)。
8.3.2. 8.3.2。 Field Initialization
场初始化
A constant variable is a
final
variable of primitive type or typeString
that is initialized with a constant expression (§15.28).常量变量是基本类型或类型
String
的final
变量,使用常量表达式(第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)).变量是否是常量变量可能对类初始化(第12.4.1节),二进制兼容性(第13.1节,第13.4.9节)和明确赋值(第16节(定义赋值))有影响。
4.12.4. 4.12.4。
final
Variables final
变量
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:常量表达式是表示基本类型值的表达式或不突然完成的
String
,仅使用以下内容组成:
- Literals of primitive type and literals of type
String
原始类型的文字和
String
类型的文字[…]
[...]
15.28. 15.28。 Constant Expressions
常数表达式
For each class or interface C, there is a unique initialization lock
LC
.对于每个类或接口C,存在唯一的初始化锁定
LC
。 The mapping from C toLC
is left to the discretion of the Java Virtual Machine implementation.从C到
LC
的映射由Java虚拟机实现决定。 The procedure for initializing C is then as follows:初始化C的过程如下:
[…]
[...]
Otherwise, record the fact that initialization of the
Class
object for C is in progress by the current thread, and releaseLC
.否则,记录当前线程正在进行C的
Class
对象初始化并释放LC
的事实。Then, initialize the
static
fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).然后,初始化C的
static
字段,它们是常量变量(§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. 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):
每个类变量,实例变量或数组组件在创建时都会使用默认值进行初始化(§15.9,§15.10.2):
[…]
[...]
- For all reference types (§4.3), the default value is
null
.对于所有引用类型(第4.3节),默认值为
null
。
It seems that this issue doesn't belong to JLS
, but we have deal with JVMS
. 看来这个问题不属于
JLS
,但我们处理JVMS
。
On Linking
stage before resolution
process there is Preparation substage, which involves: 在
resolution
过程之前的Linking
阶段有准备子阶段,其中包括:
creating the static fields for a class or interface and initializing such fields to their default values
为类或接口创建静态字段并将这些字段初始化为其默认值
and more: 和更多:
explicit initializers for static fields are executed as part of initialization (§5.5), not preparation
静态字段的显式初始化程序作为初始化(第5.5节)的一部分执行,而不是准备
while initialization includes: 初始化包括:
The execution of any one of the Java Virtual Machine instructions new
执行任何一个Java虚拟机指令都是新的
Initializing of primitive types includes writing their initial value. 初始化基元类型包括写入它们的初始值。 For reference type fields their default value is
null
because before Resolution substage jvm doesn't "know" which class is associated to apropriate symbolic reference name of a class. 对于引用类型字段,它们的默认值为
null
因为在解析子阶段之前,jvm“不知道”哪个类与类的适当符号引用名相关联。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.