Java类变量初始化的顺序是什么?

Pau*_*and 6 java

我最近遇到了这些问题,但在StackOverflow上找不到答案;

  1. Java类变量初始化的顺序是什么?
  2. 而有些相关的问题,可以重新排序变量改变类行为吗?
  3. 为什么?

正如Meta上所建议的,我将发布我对这个问题的回答.

Pau*_*and 7

在Java中,类变量按以下顺序初始化:

  1. 超类的静态变量
  2. 此类的所有静态变量都设置为其默认值.
  3. 静态变量和静态初始化块,按声明顺序排列.
  4. 超类的实例变量
  5. 此类的所有实例变量都设置为其默认值.
  6. 声明顺序中的实例变量和实例级初始化块

1和2仅在第一次实例化类时完成.

因此,给出以下代码:

class Test
  extends TestSuper
{
  final int ti1;
  final int ti2 = counter ++;
  { ti1 = counter ++; }
  static final int ts1;
  static final int ts2 = counter ++;
  static { ts1 = counter ++; }

  public static void main(String[] argv) {
    Test test1 = new Test();
    printTest(test1);
    Test test2 = new Test();
    printTest(test2);
  }
  private static void printTest(Test test) {
    System.out.print("ss2 = " + test.ss2);
    System.out.print(", ss1 = " + test.ss1);
    System.out.print(", ts2 = " + test.ts2);
    System.out.println(", ts1 = " + test.ts1);
    System.out.print("si2 = " + test.si2);
    System.out.print(", si1 = " + test.si1);
    System.out.print(", ti2 = " + test.ti2);
    System.out.println(", ti1 = " + test.ti1);
    System.out.println("counter = " + test.counter);
  }
}

class TestSuper
{
  static int counter = 0;
  final int si1;
  final int si2 = counter ++;
  { si1 = counter ++; }
  static final int ss1;
  static final int ss2 = counter ++;
  static { ss1 = counter ++; }
}
Run Code Online (Sandbox Code Playgroud)

然后我们得到以下输出:

ss2 = 0, ss1 = 1, ts2 = 2, ts1 = 3
si2 = 4, si1 = 5, ti2 = 6, ti1 = 7
counter = 8
ss2 = 0, ss1 = 1, ts2 = 2, ts1 = 3
si2 = 8, si1 = 9, ti2 = 10, ti1 = 11
counter = 12
Run Code Online (Sandbox Code Playgroud)

从此输出中我们可以看到字段按列表中指定的顺序初始化.

现在,关于第二个问题,可以重新排序字段来改变类的行为.是的,通过重新排序字段,您可以更改字段的初始化顺序.现在,在所有字段都是独立的特定情况下,这不会影响观察到的行为,但是每当字段不是独立的时,例如在上面的代码中,那么重新排序字段可以改变它们的初始值.

例如,如果三行:

  static final int ss1;
  static final int ss2 = counter ++;
  static { ss1 = counter ++; }
Run Code Online (Sandbox Code Playgroud)

改为:

  static final int ss1;
  static { ss1 = counter ++; }
  static final int ss2 = counter ++;
Run Code Online (Sandbox Code Playgroud)

然后输出将变为:

ss2 = 1, ss1 = 0, ts2 = 2, ts1 = 3
si2 = 4, si1 = 5, ti2 = 6, ti1 = 7
counter = 8
Run Code Online (Sandbox Code Playgroud)

也就是说ss2,并且ss1会改变价值观.

原因是此行为在Java语言规范中指定.