Java类和静态代码块

28
class Hello12 {
    static int b = 10;
    static {
        b = 100;
    }
}

class sample {
    public static void main(String args[]) {
        System.out.println(Hello12.b);
    }
}

运行以上代码,输出结果为100,因为当调用Hello类时,静态块首先被执行,将b的值设置为100并显示它。但是当我编写以下代码时:

class Hello12 {
    static {
         b = 100;
    }
    static int b = 10;
}

class sample {
    public static void main(String args[]) {
        System.out.println(Hello12.b);
    }
}

这里的输出结果是10。我期望的答案是100,因为一旦静态块被执行,它会给b赋值为100。所以当在main()中调用Hello.b时,它应该引用b(=100)。那么这两段代码中b的内存是如何分配的呢?

4个回答

50
在类的 "详细初始化过程" 中,JLS 的第 12.4.2 节 指出:
接下来,按文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就像它们是一个单独的块一样。
这意味着,好像第一个例子是:
b = 10;
b = 100;

第二个例子是:

b = 100;
b = 10;

最后一个赋值“获胜”,解释了你的输出。

@kocko 没关系。让我们帮助 rgettman 获得 民粹主义者 徽章。不幸的是,这意味着被接受的答案需要有10个赞... - Justin
5
如果按照“文本顺序”运行,为什么它可以编译?当静态块中设置“b”时,它显然还没有被声明。 - Holloway
因为编译器一如既往地将变量的声明与赋值分开。就像在过去的好日子里,每个变量都是先声明的,在内存中找到一个舒适的位置,然后才进行任何赋值操作;-) - Falco

16

静态块和静态变量的初始化顺序是按照它们在源代码中出现的顺序进行的。如果你的代码是:

class Hello12 {

  static int b = 10;
  static {
     b = 100;
  }

}

结果为100。


5
除了回答代码执行顺序的问题,我猜您也想知道为什么一个静态块可以引用尚未被文本声明/执行的静态变量。虽然JLS第12.4.2节解释了静态块和静态变量按它们出现的文本顺序执行,JLS第8.3.3节解释了何时可以引用什么,您可以看到使用不在赋值的左侧;的条件失败,允许第二个示例中的静态块引用尚未按文本顺序声明/执行的静态变量。

4

程序中静态变量的计算按照出现的顺序进行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接