问题1:
为什么下面的代码在没有返回语句的情况下进行编译?
public int a() {
while(true);
}
注意:如果我在片刻之后添加return,则会得到Unreachable Code Error
。
问题2:
另一方面,为什么以下代码会编译,
public int a() {
while(0 == 0);
}
即使以下情况并非如此。
public int a(int b) {
while(b == b);
}
问题1:
为什么下面的代码在没有返回语句的情况下进行编译?
public int a() {
while(true);
}
注意:如果我在片刻之后添加return,则会得到Unreachable Code Error
。
问题2:
另一方面,为什么以下代码会编译,
public int a() {
while(0 == 0);
}
即使以下情况并非如此。
public int a(int b) {
while(b == b);
}
Answers:
问题1:
为什么下面的代码在没有返回语句的情况下进行编译?
public int a() { while(true); }
这由JLS§8.4.7涵盖:
如果声明某个方法具有返回类型(第8.4.5节),则如果该方法的主体可以正常完成(第14.1节),则会发生编译时错误。
换句话说,具有返回类型的方法只能通过使用提供值return的return语句来返回;该方法不允许“掉落其主体的末端”。有关方法主体中返回语句的确切规则,请参见§14.17。
方法可能具有返回类型,但不包含任何返回语句。这是一个例子:
class DizzyDean { int pitch() { throw new RuntimeException("90 mph?!"); } }
由于编译器知道循环永远不会终止(true
当然总是如此),因此它知道该函数不能“正常返回”(丢弃其主体的末尾),因此没有问题是可以的return
。
问题2:
另一方面,为什么以下代码会编译,
public int a() { while(0 == 0); }
即使以下情况并非如此。
public int a(int b) { while(b == b); }
在这种0 == 0
情况下,编译器知道循环将永远不会终止(0 == 0
永远是真的)。但它不知道b == b
。
为什么不?
编译器理解常量表达式(第15.28节)。引用§15.2-表达式的形式 (因为奇怪的是,这句话不在§15.28中):
一些表达式的值可以在编译时确定。这些是常量表达式(第15.28节)。
在您的b == b
示例中,由于涉及到变量,因此它不是常量表达式,也没有指定在编译时确定。我们可以看到在这种情况下它总是正确的(尽管QBrute 指出如果b
是a double
,我们很容易被愚弄,这不是它本身),但是JLS仅指定了常量表达式是在编译时确定的,它不允许编译器尝试评估非常数表达式。bayou.io 提出了一个很好的理由,为什么不这样做:如果您开始尝试在编译时确定涉及变量的表达式,那么该在哪里停下来?很明显(对于非Double.NaN
==
b == b
NaN
值),那又如何a + b == b + a
呢?还是(a + b) * 2 == a * 2 + b * 2
?以常数画线很有意义。
因此,由于它不“确定”表达式,因此编译器不知道循环永远不会终止,因此认为该方法可以正常返回-不允许这样做,因为它必须使用return
。因此它抱怨缺少一个return
。
查看字节码,如果返回的内容与定义不匹配,则会收到编译错误。
例:
for(;;)
将显示字节码:
L0
LINENUMBER 6 L0
FRAME SAME
GOTO L0
注意缺少任何返回字节码
这永远不会返回,因此不会返回错误的类型。
为了进行比较,可以使用以下方法:
public String getBar() {
return bar;
}
将返回以下字节码:
public java.lang.String getBar();
Code:
0: aload_0
1: getfield #2; //Field bar:Ljava/lang/String;
4: areturn
注意“ areturn”,意思是“返回参考”
现在,如果我们执行以下操作:
public String getBar() {
return 1;
}
将返回以下字节码:
public String getBar();
Code:
0: iconst_1
1: ireturn
现在我们可以看到定义中的类型与ireturn的返回类型不匹配,这意味着return int。
因此,真正的原因在于,如果该方法具有返回路径,则该路径必须与返回类型匹配。但是字节码中有一些实例,根本没有生成返回路径,因此不会破坏规则。