我对加载课程的过程感到困惑。执行类成员的顺序是什么?
请参阅以下内容:
class L {
static void fr(){
a=1;
b=3;
a=b;
}
static{
a=3;
b=1;
a=b;// here the problem:cannot reference a field before it is defined
}
static int a;
static int b;
public static void main(String args[]) {
}
}
每当我将a
和b
的声明移到静态块之前的顶部时,编译工作正常。所以我需要了解这些东西如何解决上述问题。
答案 0 :(得分:4)
在Java中,如果类变量不是初始化它的表达式,则在声明它之前引用它是非法的。 Java将以文本顺序在类中执行初始值设定项。
接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就像它们是单个块一样。
使用类变量,其声明在使用后以文本形式出现有时受到限制,即使这些类变量在范围内(第6.3节)。具体来说,如果满足以下所有条件,则为编译时错误:
在使用类变量后,类或接口C中的类变量声明以文本形式出现;
在C的类变量初始值设定项或C的静态初始值设定项中,use是一个简单的名称;
使用不在作业的左侧;
C是封闭使用的最里面的类或接口。
所有这些都是真的。声明在a=b;
中使用后出现。它在静态初始化器中。它不在作业的左侧,而且它是最里面的(唯一)类。
最简单的编译方法是将声明移到源代码中的静态初始化程序之上。
有趣的是,将a=b;
替换为a=L.b;
也会将其编译,因为对b
的引用不再是“简单”。
答案 1 :(得分:0)
首先加载类并验证整体结构。然后验证方法并检查外部链接。然后执行静态init。这是执行静态块的时候。
但你的问题显然是编译器,而不是类加载。您需要将静态变量声明移到静态块之上。与课程加载完全无关。
提示:了解编译时错误和运行时异常之间的区别。你看到的是来自编译器的错误消息。 (你很幸运,你没有抓到血腥的地狱并关闭投票,因为你的问题中没有包含确切的错误信息。)