我如何告诉Java我不需要初始化a以获得有效的程序并且不给我错误?
int a;
boolean b = true;
while (true) {
if (b == false) {
System.out.print(a);
break;
} else {
b = false;
a = 5;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我不能,那么为什么这就是编译器的设计方式?
是否容易设计这样的编译器,或者这是一种确保我重构代码的机制?
这是不一样的问题,这一个
Ste*_*n C 10
是'错误:变量a可能没有被初始化'在这个if构造中真的有必要吗?
是的,这是必要的.Java语言规范需要它.这在JLS 16 - Definite Assignment中有所介绍.
"当对其值进行任何访问时,每个局部变量(第14.4节)和每个空白最终字段(第4.14.4节,第8.3.1.2节)必须具有明确赋值."
我如何告诉Java我不需要初始化
a以获得有效的程序并且不给我错误?
你无法告诉Java.您需要初始化变量...或重构代码.
如果我不能,那么为什么这就是编译器的设计方式?
因为Java编译器必须实现规范,否则它不是一个合适的Java编译器.规范说这是一个错误.
真正的问题是规范说明的原因.答案是,编译器编写者不必在所有Java编译器中包含困难的定理证明代码.
在您给出的示例中,程序员很明显该变量将始终被初始化.但是,编译器需要验证它.它需要绝对确定,因为未初始化的变量将具有未定义的行为.
自动(无向)验证是一项复杂的任务.复杂意味着要编写更多(编译器)代码,更多(编译器)错误等等.
这项技术的"最新技术"并不适合对复杂的Java代码进行这种分析.
存在(理论上)情况,其中验证变量被初始化在数学上是不可能的.
所以...明智地......指定Java语言的人将其推回给程序员.根据JLS中规定的规则,您需要编写代码,以便在使用前明确分配变量.
还有第二个原因.假设JLS确实允许Java编译器接受
System.out.print(a);
Run Code Online (Sandbox Code Playgroud)
当且仅当它能够满足自己a以前(始终)先前已初始化.现在考虑由不同的人(或不同时间的同一个人)编写的两个Java编译器来实现相同版本的JLS.
编译器C1可以确定a总是初始化,并说该程序是有效的.
编译器C2无法弄清楚a总是初始化,并说该程序无效.
我们现在有两个表面上实现相同版本JLS的Java编译器,但不同意您的示例程序(上面)是否有效.这根本站不住脚.
为了进一步复杂化,我怀疑当JVM验证刚刚加载的字节码时,也必须发生类似于"明确赋值"检查的内容.因此,对JLS明确赋值规则的更改将会影响到JVMS,并可能影响JVM平台对其他编程语言和直接编译/生成JVM字节码的工具的行为.