所以我只是编程了一下,当我遇到一些非常不需要的行为时,发现了一些非常奇怪的Java。让我们看一下(精简的)代码:
public class Main {
static{
test = "test2"; // this is fine!?
System.out.println(test); //compilation error!
}
static String test = "test1"; // initialization line
public static void main(String[] args) {
System.out.println(test);
}
}
此程序会为您提供编译时错误,说明您无法参考" test"在定义之前。但是我之前只做了一行。现在猜出当你注释掉错误行时输出是什么......
输出为:" test1",因此初始化会覆盖声明之前发生的分配!
此外,如果您没有初始化变量," test2"是输出。但是,如果您明确指定" null"作为初始化期间的值,输出将为" null"。
问题:
答案 0 :(得分:3)
这是JLS中定义的预期行为。回答你的问题:
回答了这个问题
- 为什么我可以在声明变量之前访问要写入但不读取的变量?
醇>
成员声明只有在成员是类或接口C的实例(分别是静态)字段并且满足以下所有条件时才需要以文本方式显示:
用法发生在C的实例(分别是静态)变量初始值设定项或C的实例(分别是静态)初始值设定项中。
用法不在作业的左侧。
用法是通过一个简单的名称。
C是封闭用法的最里面的类或接口。
如果不满足上述四项要求中的任何一项,则为编译时错误。
因此,由于赋值的左侧是赋值 ,因此明确不引用必须在声明之后的情况之一。
- 为什么在第一次分配后完成初始化(这与术语“初始化”相矛盾)?
醇>
这由section 12.4.2回答。
接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就像它们是单个块一样。
所有初始化都发生在它们位于静态初始化块内,按照相对于每个其他初始化或静态块的顺序出现。该字段以其默认值null
开头,在静态块中使用,然后进行初始化。
- 我一直认为用“null”显式初始化与省略初始化相同。对于这个例子来说,这显然是错误的...我只是想错了或者这与规范相矛盾吗?
醇>
由于你在这里看到的原因,它们并不完全相同。如果在初始化发生之前修改静态块中的值,它将在静态初始化阶段被设置回null。
- 这真的是想要的Java行为吗?这是一个错误吗?
醇>
是的,这是想要的行为。正如上面链接的JLS部分所示,这不仅仅是一个意想不到的事情。有关它的规则明确规定允许这样做。