Java 构造函数与内联字段初始化

Java constructor vs inline field initialisation

如果我有以下代码:

public class Test {

   private int x = 5;
   private static int y = 5;

   public Test() {
      x = 10;
      y = 10;
   }
}

我想知道在这两种情况下它实际上是否会最初分配 5,然后用 10 更新它,换句话说,初始化一个内联变量和在构造函数中没有意义,因为它实际上具有初始化一个变量的效果变量两次?或者在 x(作为实例字段)的情况下,它只是将 x = 5 替换为 x = 10,因此甚至只有 运行 x = 10?

知道反编译版本就好了

当您使用这样的赋值语句声明变量时,该值将成为该变量的默认值。如果您不更改它,它将始终 return 该值。如果您覆盖默认值,它将 return 改为

I'm wondering in both cases will it actually initially assign 5, and then update this with 10

是的。构造函数将:

  1. 呼叫super().
  2. 执行任何内联初始化和匿名初始化块。
  3. 执行构造函数的剩余主体。

这在 JLS #12.5-6 中有更详细的说明。

编译器不会进行此类优化 - 实际上进行此类微优化毫无意义(您可以确保使用 javap)。

此外,语言规范规定这些值按某种顺序分配。而且这些步骤在逻辑上应该是不同的步骤,没有合并。

简单的流程是:
1.父class初始化
2. 静态字段和静态部分按照它们在源文件中出现的顺序初始化
3.字段初始化和实例部分初始化按照它们在源文件中出现的顺序
4.构造函数执行

示例:

public class TestClass {
    private int a = 5;
    {
        a = 10; 
    }

    private static int b = 10;

    static {
        b = 15;
    }

    public TestClass() {
        System.out.println(a + ", " + b);
        a = 20;
        b = 30;
        System.out.println(a + ", " + b);
    }

    public static void main(String args[]) {
        TestClass t = new TestClass();
    }
}

输出:

10, 15
20, 30

当JVM加载class时,它实际上加载Test.class并为静态变量如y分配内存。任何成员变量,例如 x 只会在构造对象时初始化,例如 new Test();