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

Java constructor vs inline field initialisation

本问题已经有最佳答案,请猛点这里访问。

如果我有以下代码:

1
2
3
4
5
6
7
8
9
10
public class Test {

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

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

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

了解反编译版本会很高兴。


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

对。施工单位将:

  • 呼叫super()
  • 执行任何内联初始化和匿名初始化块。
  • 执行构造函数的其余主体。
  • 这在JLS 12.5-6中有更详细的说明。


    编译器不会进行这种优化——实际上没有必要进行这种微优化(您可以确保使用javap)。

    此外,语言规范还规定了这些值的分配顺序。这些步骤在逻辑上应该是不同的步骤,而不是组合在一起的。


    当jvm加载类时,它实际上加载test.class并为静态变量(如y)分配内存。任何成员变量(如x)都只能在构造new test()之类的对象时初始化;


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

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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();
        }
    }

    输出:

    1
    2
    10, 15
    20, 30


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