最终字段初始化顺序 [英] Final fields initialization order

查看:94
本文介绍了最终字段初始化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一些在尚未初始化的类上调用静态方法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)。


8.3.2。字段初始化


常量变量 final 基本类型或类型的变量 String 使用常量表达式初始化(​​第15.28节)。变量是否是常量变量可能对类初始化(第12.4.1节),二进制兼容性(第13.1节,第13.4.9节)和明确赋值(第16节(定义赋值))有影响。


4.12.4。 final 变量


常量表达式是一个表示基本类型值的表达式或 String ,它不会突然完成,只使用以下内容组成:




  • 原始类型和文字类型的文字字符串



[...]


15.28。常量表达式


对于每个类或接口C,都有一个唯一的初始化锁 LC 。从C到 LC 的映射由Java虚拟机实现决定。初始化C的过程如下:



[...]


  1. 否则,记录当前线程正在进行C的 Class 对象的初始化,并释放 LC



    然后,初始化C的 static 字段,它们是常量变量( §4.12.4,§8.3.2,§9.3.1)。


[...]


  1. 接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,好像它们只是一个块。


12.4.2。详细的初始化过程


程序中的每个变量在使用其值之前必须具有值:




  • 每个类变量,实例变量或数组组件在创建时都会使用默认值进行初始化(§15.9,§15.10.2): / p>

    [...]




    • 对于所有参考类型(§4.3),默认值value是 null



4.12.5。变量的初始值


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 other static 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.

8.3.2. Field Initialization

A constant variable is a final variable of primitive type or type String 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)).

4.12.4. final Variables

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

[…]

15.28. Constant Expressions

For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. The procedure for initializing C is then as follows:

[…]

  1. Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.

    Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).

[…]

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆