boolean method(int value) {
switch(value) {
case 0:
return false;
case 1:
return true;
default:
Assert.fail("Unhandled value.");
}
}
这会导致编译失败,并返回错误"Method must return a result",即使Assert.fail()
只抛出AssertionError
。如果我自己抛出一个AssertionError
而不是调用Assert.fail()
,它就会编译。
编译器无法知道Assert.fail
总是抛出异常,除非它深入研究该方法的字节码并对其进行某种静态分析(一旦你开始了这种事情,你该在哪里停止?(。Java语言规范规定(第8.4.7节(
如果一个方法被声明为具有返回类型,那么如果该方法的主体能够正常完成,则会发生编译时错误(§14.1(
在你的例子中,"可以正常完成"可以归结为(第14.21节(
非开关块的非空块可以正常完成,如果其中的最后一条语句可以正常完成。
方法中的最后一个语句是switch
语句:
switch语句可以正常完成,如果以下至少一项为真:
[…]
- 开关块中的最后一条语句可以正常完成
switch
中的最后一条语句是表达式语句(方法调用(
表达式语句可以正常完成,前提是它是可访问的。
即,规范特别指出编译器不应查看任何方法调用内部,并且任何方法调用表达式都必须被视为可以正常完成的表达式。
同一节还定义了
break
、continue
、return
或throw
语句无法正常完成。
因此,为了让编译器满意,您需要在方法的末尾添加一个return或throw
// will never be reached
throw new Error();
我个人会投一投,并评论解释说,如果达到这条线,就会出现严重问题。。。
编译器不可能知道Assert.fail()
总是抛出异常,因此编译器仍然需要return
语句(或Ian Roberts建议的显式throw
(。当显式地对throw new AssertionError()
进行编码时,编译器肯定知道无法达到方法的结束}
,并且不需要return
。
对于所有代码路径,必须始终有一个返回值或一个异常。编译不知道Assert.fail并不总是抛出异常