javaclassloader的准备阶段和初始化阶段

Preparation stage and initialization stage of java class loader

我无法理解以下各行之间的区别 (http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.2)

A) 准备工作包括将静态字段初始化为默认值。

B) class 的初始化包括对 class.

中声明的静态字段(class 变量)执行初始化程序

是否意味着 'a' 将在 "preparation" 阶段分配默认值,而 'b' 将在 "Initialization" 阶段分配默认值:

static int a;  
static int b=2;

"Initializing to default values" 表示字段设置为以下值:

  • 布尔值:假
  • 整数、长、字节、短:0
  • 双精度,浮点数:+0.0
  • char: '\u0000'
  • 引用类型:null

"Initializing by executing initializers" 意味着现在分配给那些静态字段的表达式被评估并分配给它们。

因此,在 "preparation" 阶段,您的 ab 将被创建并接收值 0。在"initialization"阶段,b会收到值2.


使用有副作用的方法很容易验证这一点。我们不是将简单的“2”分配给 b,而是调用一个静态方法 returns 值 2,但它还会在执行此操作之前打印有关变量的信息:

public class SimpleTest {

    private static int a;
    private static int b = printAAndBReturning2("initializer");

    static {
        printAAndBReturning2("static initializing block");
    }

    public static void main(String[] args) {

        printAAndBReturning2("main");

    }

    public static int printAAndBReturning2(String where) {
        System.out.printf("In %s a is %d and b is %d%n", where, SimpleTest.a, SimpleTest.b);
        return 2;
    }
}

输出为:

In initializer a is 0 and b is 0
In static initializing block a is 0 and b is 2
In main a is 0 and b is 2

此演示还用于警告您在初始化阶段使用 运行 的方法。

原始类型的所有字段将自动初始化为默认值。
因为int是0。所以a == 0。您可以检查默认值 here.
它在非原始类型上有所不同(类)。
所以
Font a; -> a == null(如果您尝试使用 a 的方法,您将得到 a is not initialized
Font b = new Font("Dialog", 16, Font.BOLD); -> b == ...(我想你明白了)。