静态块初始化

这是一段Java代码:

static { ture = 9; } static int ture; { // instance block System.out.println(":"+ture+":"); } 

它是如何编译的? 初始化后已执行变量’ture’的声明。 据我所知,静态块和字段按照它们出现的顺序执行。

现在为什么实例块中的值9已被打印3次? 顺便说一下,类的实例已经创建了3次。 这不是作业,我正在学习Java认证。

关于第一个问题,静态块确实按它们出现的顺序处理,但是在静态块之前首先处理声明。 声明作为类的准备 ( JLS§12.3.2 )的一部分进行处理,它在初始化之前发生( JLS§12.4.2 )。 出于学习目的,整个JLS§12可能是有用的,以及JLS§8 ,特别是§8.6和JLS§8.7 。 (感谢Ted Hopp并且因为召集这些部分而声名狼借 。)

引用的代码中没有足够的信息来回答您的第二个问题。 (无论如何,在SO上最好每个问题提出一个问题。)但是例如:

 public class Foo { static { ture = 9; } static int ture; { // instance block System.out.println(":"+ture+":"); } public static final void main(String[] args) { new Foo(); } } 

…仅输出:9: 一次 ,因为只创建了一个实例。 如果删除new Foo();它根本不会输出它new Foo(); 线。 如果您看到:9:三次,那么您将在未显示的代码中创建三个实例。

静态初始化程序按它们出现的顺序执行,并且根本不执行声明 ,这就是它们的名称。 这就是您的代码编译没有问题的原因:类结构在编译时从声明组装,静态块在运行时执行,很久之后处理完所有声明。

正如其他人所说,声明的地方通常是无关紧要的。

但有时它可能会引起混淆:

 class Z { static int i = j + 2; // what should be the value of j here? static int j = 4; } 

所以Java确实在前向引用上添加了一些限制: http : //docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.2.3

您的示例是允许的,因为该字段的使用位于作业的左侧。 显然语言设计师并不认为这太混乱了。 然而,如果可以的话,我们应该总是避免前向参考。