为什么方法在抛出异常后不需要 return 一个值?

Why don't methods need to return a value after throwing an exception?

这是一个人为的例子。我有一个非 void 方法,它抛出异常。为什么之后我不必 return 一个值?毕竟方法是非void的

public static Toast makeText(Context context, CharSequence text, int duration) {
    throw new RuntimeException("Stub!");
    //Must return something from here but there is not, Why?
}

抛出异常会中断控制流,立即退出方法。抛出异常时,不需要 return 值,因为 调用 方法的代码未正常完成。例如,在下面的代码中,不需要 foo 到 return 一个数字,因为 int x = foo(); 没有成功,而是传播异常:

int foo() {
    throw new RuntimeException();
}
void bar() {
    int x = foo();
    // This line will not be reached
    System.out.println(x);
}

由于 int x = foo(); 之后的代码无论如何都不会执行,因此 x 不需要从 foo 接收 return 值,因此 foo 不需要提供 return 值。

事实上,一个方法不能既 return 一个值又抛出一个异常,因为 return 一个值意味着该方法正常完成。

没有实际要求方法 returning 值包含 return 语句。也许令人惊讶的是,这段代码是合法的:

int noReturn() {
  while (true) {}
}

语言规范的关键 big 是 JLS 8.4.7,它表示:

If a method is declared to have a return type (§8.4.5), then a compile-time error occurs if the body of the method can complete normally (§14.1).

“正常完成”在JLS 14.1中有描述:

Every statement has a normal mode of execution in which certain computational steps are carried out. The following sections describe the normal mode of execution for each kind of statement.

If all the steps are carried out as described, with no indication of abrupt completion, the statement is said to complete normally. However, certain events may prevent a statement from completing normally:

  • The break, yield, continue, and return statements (§14.15, §14.21, §14.16, §14.17) cause a transfer of control that may prevent normal completion of expressions, statements, and blocks that contain them.
  • Evaluation of certain expressions may throw exceptions from the Java Virtual Machine (§15.6). An explicit throw (§14.18) statement also results in an exception. An exception causes a transfer of control that may prevent normal completion of statements.

所以:要求是方法一定不能正常完成;并且 returnthrow 都是导致方法异常完成的方法。


请注意,这并不是说该方法必须异常完成而是:return开始时的 while 循环示例,它不会正常或异常完成:因为循环条件是常量 true,并且不包含 return、throw 或 break 或可能引发异常的语句,该循环永远不会完成,这也很好(至少从语言的角度来看)。