问题1:
为什么下面的代码编译时没有 return 语句?
public int a() {
while(true);
}
注意:如果我在一段时间后添加 return ,那么我会得到一个
Unreachable Code Error
。问题2:
另一方面,为什么下面的代码会编译,
public int a() {
while(0 == 0);
}
即使下面没有。
public int a(int b) {
while(b == b);
}
最佳答案
这被 JLS§8.4.7 覆盖:
由于编译器知道循环永远不会终止(当然 true
始终为真),它知道该函数不能“正常返回”(从其主体的末尾处退出),因此没有 return
是可以的。
在 0 == 0
的情况下,编译器知道循环永远不会终止(0 == 0
将始终为真)。但它 不知道 b == b
。
为什么不?
编译器理解 constant expressions (§15.28) 。引用 §15.2 - Forms of Expressions(因为奇怪的是这句话不在 §15.28 中):
在您的 b == b
示例中,由于涉及变量,因此它不是常量表达式,并且未指定在编译时确定。 我们可以看到,它总是要在这种情况下,真正的(尽管如果b
是一个double
,作为QBrute pointed out,我们可以很容易地通过Double.NaN
,这是not ==
itself上当),但JLS唯一指定该常量表达式确定在编译时,它不允许编译器尝试评估非常量表达式。 bayou.io raised a good point 为什么不:如果你开始尝试在编译时确定涉及变量的表达式,你会在哪里停下来? b == b
很明显(呃,对于非 NaN
值),但是 a + b == b + a
呢?还是 (a + b) * 2 == a * 2 + b * 2
?在常量处画线是有道理的。
因此,由于它不“确定”表达式,编译器不知道循环永远不会终止,因此它认为该方法可以正常返回 - 这是不允许的,因为它需要使用 return
。所以它提示缺少 return
。
关于具有返回类型的 Java 方法在没有返回语句的情况下编译,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31050114/