为啥方法在抛出异常后不需要返回值?
Posted
技术标签:
【中文标题】为啥方法在抛出异常后不需要返回值?【英文标题】:Why don't methods need to return a value after throwing an exception?为什么方法在抛出异常后不需要返回值? 【发布时间】:2022-01-14 22:38:41 【问题描述】:这是一个人为的例子。我有一个非 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?
【问题讨论】:
该方法总是无条件地以异常结束。以异常结束的方法没有返回值,因为它抛出了异常。我建议您学习 Java 中异常的基础知识以及如何处理它们。 你在哪里使用这个方法! 嗨。我建议你谷歌“函数中的 return 语句如何工作”。当你有基本的想法时,你应该谷歌“抛出和处理异常”。互联网上有大量信息。祝你好运! 异常进入一个特殊的控制流并结束常规的方法控制流。该方法是 exit,Java 会遍历调用堆栈,直到找到捕获此异常事件的 try-catch。如果没有找到,程序结束。特别是,该方法不继续,因为它没有“正常”结束,所以它也没有返回任何值。 @Zabuzard 首先感谢您编辑标题,因为我的标题不清楚。正如你所说,我将研究 Java 中的异常,因为我不记得我做过这样的事情。谢谢。 【参考方案1】:抛出异常会中断控制流,立即退出方法。当抛出异常时,不需要返回值,因为调用该方法的代码没有正常完成。例如,在下面的代码中,foo
不需要返回数字,因为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
接收返回值,因此foo
不需要提供返回值。
事实上,一个方法不能既返回值又抛出异常,因为返回值意味着方法正常完成。
【讨论】:
补充一点,假设bar()
的作者不知道foo()
可以抛出并想象bar()
将是非无效的。如果方法在得到异常后需要返回值,他怎么知道int x = foo(); return x + 5;
是不安全的并且没有到达最后一行?如果你仔细考虑一下,那将是完全混乱的。
@Zabuzard 如果假设方法即使在抛出异常时也需要返回值,那么int x = foo(); return x + 5;
就可以了; x
会有一个值,因为 foo
必须返回一个值。这只是意味着异常必须不中断控制流。你可以设计这样的语言;实际上它与在 C 中处理错误的方式非常相似,在 C 中不是抛出异常来指示错误条件,而是设置错误标志并继续执行,假设调用者在关心是否发生错误时会检查错误标志.
“因为返回值意味着方法正常完成”这是不正确的,或者至少使用了与 Java 中“正常完成”的含义不同的术语:返回值被认为是异常完成。
@AndyTurner 表示方法invocation会正常完成,即int x = foo();
这一行。根据 JLS,return
语句本身不会“正常完成”,但 return
语句不是方法。
@kaya3 然后说方法调用:)【参考方案2】:
实际上并没有要求返回值的方法包含返回语句。也许令人惊讶的是,这段代码是合法的:
int noReturn()
while (true)
语言规范的关键是JLS 8.4.7,它说:
如果将方法声明为具有返回类型(第 8.4.5 节),则如果方法的主体可以正常完成(第 14.1 节),则会发生编译时错误。
JLS 14.1中描述了“正常完成”:
每个语句都有一个正常的执行模式,其中执行某些计算步骤。以下部分描述了每种语句的正常执行模式。
如果所有步骤都按描述执行,没有任何突然完成的迹象,则称该语句正常完成。但是,某些事件可能会阻止语句正常完成:
break、yield、continue 和 return 语句(第 14.15 节、第 14.21 节、第 14.16 节、第 14.17 节)会导致控制权转移,这可能会阻止包含它们的表达式、语句和块的正常完成。 某些表达式的计算可能会从 Java 虚拟机中引发异常(第 15.6 节)。显式 throw (§14.18) 语句也会导致异常。异常会导致控制权转移,这可能会阻止语句的正常完成。
所以:要求是方法不能正常完成;而return
和throw
都是导致方法异常完成的方式。
请注意,这并不是说该方法必须异常完成:返回到开头的 while 循环示例,它不会正常或异常完成:因为循环条件是一个常量 true,并且不会包含 return、throw 或 break 或可能引发异常的语句,该循环永远不会完成,这也很好(至少从语言的角度来看)。
【讨论】:
以上是关于为啥方法在抛出异常后不需要返回值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥内部异常到达 ThreadException 处理程序而不是实际抛出的异常?