为什么实例初始化程序块在声明之前先引用一个字段? [英] Why can my instance initializer block reference a field before it is declared?
问题描述
我的理解是,在声明变量之前不能引用它,并且在类的主体内但在任何方法之外的所有代码(包括实例初始化器)将在构造函数之前按顺序执行.对象被创建( static
变量和初始化程序块除外,它们在程序开始时按顺序运行,以初始化整个类).那么,为什么下面的代码会编译(并运行!):
My understanding is that you cannot reference a variable before it has been declared, and that all code (including instance initializers) that is within the body of a class, but outside of any method, is executed in order before constructor when the object is created (the exception being static
variables and initializer blocks, which are run in order at the beginning of the program, to initialize the entire class). Why, then, does the following code compile (and run!):
public class WhyIsThisOk {
{ a = 5; } // why is this ok???
int a = 10;
public WhyIsThisOk() {
}
public static void main(String[] args) {
WhyIsThisOk why = new WhyIsThisOk();
System.out.println(why.a); // 10
}
}
推荐答案
来自 Java编译器将初始化程序块复制到每个构造函数中.因此,该方法可用于在两个程序之间共享一个代码块多个构造函数.
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors. 上面的陈述有些误导,因为如果按照上面文档的解释,我们可以像这样重写原始代码: The above statement is slightly misleading, because if we follow the explanation of the above doc we can rewrite the original code like this: 但是运行 But running 但是实际上,初始化程序块和变量赋值都被复制到构造函数中: But in reality it is both the initializer block and variable assignment are copied into constructor: 更新: 这是 doc 详细描述初始化顺序和构造函数调用: Here is the doc describing in detail the initialization order and constructor invocation: 4)执行实例初始化器和实例变量此类的初始化程序,分配实例变量的值初始化为对应的实例变量,在从左到右的顺序,它们在源代码中以文本形式显示上课.如果执行这些初始化程序中的任何一个都会导致异常,则不会再处理其他初始化程序,并且这程序突然完成,但有相同的例外.除此以外,继续执行步骤5. 4) Execute the instance initializers and instance variable
initializers for this class, assigning the values of instance variable
initializers to the corresponding instance variables, in the
left-to-right order in which they appear textually in the source code
for the class. If execution of any of these initializers results in an
exception, then no further initializers are processed and this
procedure completes abruptly with that same exception. Otherwise,
continue with step 5. 5)执行此构造函数的其余部分.如果执行突然完成,然后此步骤突然完成同样的原因.否则,此过程将正常完成. 5) Execute the rest of the body of this constructor. If that execution
completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally. 这篇关于为什么实例初始化程序块在声明之前先引用一个字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
public class WrongVersionOfWhyIsThisOk {
int a = 10;
public WhyIsThisOk (){
a = 5;
}
public static void main(String[] args){
WrongVersionOfWhyIsThisOk why = new WrongVersionOfWhyIsThisOk ();
System.out.println(why.a);
}
}
WrongVersionOfWhyIsThisOk
会产生5而不是原始代码产生的10.WrongVersionOfWhyIsThisOk
will produce 5 instead of 10 that original code produces. public class RightVersionOfWhyIsThisOk {
int a;
public RightVersionOfWhyIsThisOk (){
a = 5;
a = 10;
}
public static void main(String[] args){
RightVersionOfWhyIsThisOk why = new RightVersionOfWhyIsThisOk ();
System.out.println(why.a);
}
}