这是Java。我理解1 index
的赋值是initialization block
,它是在实例化类时首次运行的,但为什么这个有效?
public class arr {
{
index = 1;
}
int index;
void go() {
System.out.println(++index);
}
public static void main(String [] args){
new arr().go();
}
}
输出为2。
我应该收到symbol not found
编译错误。此行为是初始化块原生的吗?在正常方案int index;
应该出现在index = 1;
之前。
答案 0 :(得分:5)
+1,看起来很奇怪。但事实上,非静态初始化块只是由javac插入到对象构造函数中。如果我们反编译arr.class,我们将获得真正的代码
public class arr {
int index;
public arr() {
index = 1;
}
void go() {
System.out.println(++index);
}
public static void main(String args[]) {
(new arr()).go();
}
}
让你更有趣地考虑这个难题
public class A {
int index;
A() {
index = 2;
}
{
index = 1;
}
}
什么是新的A()。索引?正确的答案是2.参见反编译的A.class
class A {
int index;
A() {
index = 1;
index = 2;
}
}
也就是说,非静态初始化块首先出现在对象构造函数
中答案 1 :(得分:4)
非静态初始化块在构造函数之后运行,因此代码正确且输出符合预期。
答案 2 :(得分:4)
代码的顺序无关紧要。正如您所说,
在正常场景中int index;应该在index = 1之前;
这正是声明字段所发生的情况,然后分配值1。编译器不关心类中这些项的物理排序。
答案 3 :(得分:2)
从Java Tutorial开始,Java编译器将初始化程序块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。
以下是使用final方法初始化实例变量的示例:
class Whatever {
private varType myVar = initializeInstanceVariable();
protected final varType initializeInstanceVariable() {
// initialization code goes here
}
}
答案 4 :(得分:1)
一个类可以有任意数量的静态初始化块,它们可以出现在类体中的任何位置。
此外,它与变量相同,您可以在声明之前“使用”:
class T {
public static void main(String[] args) {
T t = new T();
System.out.println(t.a);
}
public int a = 14;
}
答案 5 :(得分:1)
与某些语言(例如C)不同,类(静态)变量和实例变量的声明的顺序与Java无关。您可以在声明之前引用类/实例变量(文本)。所以即使这是有效的......
public class X {
private int a = b;
private int b = a;
...
}
......虽然初始化程序实际上没有实现任何有用的东西。
答案 6 :(得分:0)
Java是一种语言,可以在执行任何特技之前完全解析您的代码(我试图避免无聊的编译器细节)。因此,如果您的初始化程序块在字段声明之前出现并不重要,则会有特定的顺序发生。类加载(当然还有字段加载),静态初始化器,构造函数,非静态初始化器都在任何方法调用之前运行(可以在不执行构造函数和非静态成员的情况下执行静态调用)。 您应该考虑阅读一些SCJP(现在的OCPJP)书籍,如“K& B”,以真正了解幕后发生的事情。像“JVM internals”这样的教程在这个阶段可能会有些过分(但你应该考虑将它保存在你的存档中以供以后引用)。