我如何告诉 Java 我不需要初始化 a
来拥有一个可以工作的程序并且不会给我一个错误?
int a;
boolean b = true;
while (true) {
if (b == false) {
System.out.print(a);
break;
} else {
b = false;
a = 5;
}
}
如果我不能,是否有理由这样做编译器的设计方式?
设计这样的编译器是否容易,或者这是确保我重组代码的机制?
这与 this one 不是同一个问题
最佳答案
Is 'error: variable a might not have been initialized' really necessary in this if construct?
是的,有必要。 Java 语言规范需要它。 JLS 16 - Definite Assignment 中对此进行了介绍。 .
<小时/>"Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs."
How do I tell Java that I don't need to initialize
a
to have a working program and to not give me an error?
你不能告诉Java这一点。您需要初始化变量...或重构代码。
<小时/>And if I can't, is there a reason why this is the way the compiler was designed?
因为Java编译器必须实现该规范,否则它就不是一个合适的Java编译器。规范说这是一个错误。
真正的问题是为什么规范这么说。答案是,编译器编写者不必被迫在所有 Java 编译器中包含困难的定理证明代码。
在您给出的示例中,对于程序员来说很明显变量将始终被初始化。然而,编译器需要验证它。它需要绝对确定,因为未初始化的变量将具有未定义行为。
自动(无向)验证是一项复杂的任务。复杂意味着需要编写更多(编译器)代码、更多(编译器)错误等等。
这项技术的“最先进水平”不足以对复杂的 Java 代码进行这种分析。
在某些(理论上)情况下,验证变量是否已初始化在数学上是不可能的。
所以......明智地......指定 Java 语言的人将其推回给程序员。您需要编写代码,以便根据 JLS 中规定的规则,在使用之前明确地分配变量。
还有第二个原因。假设 JLS 确实允许 Java 编译器接受
System.out.print(a);
当且仅当它可以满足自己a
(总是)先前初始化的要求。现在考虑由不同人(或同一个人在不同时间)编写的两个 Java 编译器来实现相同版本的 JLS。
编译器 C1 可以判断出
a
始终已初始化,并表明该程序是有效的。编译器 C2 无法识别出
a
始终已初始化,并表示该程序无效。
我们现在有两个 Java 编译器,表面上实现了相同版本的 JLS,但在您的示例程序(上面)是否有效方面存在分歧。这根本站不住脚。
<小时/>让事情变得更加复杂的是,我怀疑当 JVM 验证刚刚加载的字节码时,也一定会发生类似于“明确赋值”检查的事情。因此,对 JLS 明确赋值规则的更改将波及 JVMS,并可能影响直接编译/生成 JVM 字节码的其他编程语言和工具的 JVM 平台行为。
关于java - 'error: variable a might not have been initialized' 在这个 if 构造中真的有必要吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52564375/