Java 让异常向上移动调用堆栈的价值是什么?

Java 让异常向上移动调用堆栈的价值是什么?,java,exception,try-catch,Java,Exception,Try Catch,我只是在做一些简单的异常处理,我在“传播IOExceptions”一节中读到了一些让我有点困惑的东西。Jenkov说,如果方法C抛出一个IOException-public void MethC()抛出IOException{},但没有一个try-catch来处理它,它会将调用堆栈上卷到一个调用方法,该调用方法可能有一个try-catch来处理异常 try-catch-finally块的全部目的似乎是处理一个异常,该异常未经处理会使程序崩溃,对吗?那么,为什么要让异常回滚到调用堆栈中链上某个位置

我只是在做一些简单的异常处理,我在“传播IOExceptions”一节中读到了一些让我有点困惑的东西。Jenkov说,如果方法C抛出一个
IOException
-
public void MethC()抛出IOException{}
,但没有一个
try-catch
来处理它,它会将调用堆栈上卷到一个调用方法,该调用方法可能有一个
try-catch
来处理异常


try-catch-finally
块的全部目的似乎是处理一个异常,该异常未经处理会使程序崩溃,对吗?那么,为什么要让异常回滚到调用堆栈中链上某个位置的
try catch
?价值是什么?如果有什么不同的话,在我看来,让异常在整个调用链上滚动,而不是立即处理它,只会损害程序的正常运行,导致效率低下或效率低下。

只要您的设计需要,让异常在调用堆栈中渗透是完全可以的。一个简单的例子是,如果您的
main
方法在一个调用周围有一个
try
/
catch
块,该块可以具有非常深的调用堆栈。如果在任何一点发生错误,它都可以抛出异常,程序可以优雅地结束,在
main
中的
catch
说“对不起,发生了以下异常,因此程序正在结束”

从不捕捉异常并让程序异常终止是一种糟糕的设计,但是从实际异常发生的地方多个层次捕捉它并没有什么错,如果在实例中这样做是有意义的话


问题通常发生在代码的深处,正确的处理方法(显示对话框?打印错误?安静地处理?)通过不同的调用路径可能会有所不同,并且可以在调用堆栈的其他地方选择要执行的操作。

通常,应在调用堆栈中能够处理异常的位置处理异常

例如,假设您有一个库方法,该方法采用文件路径并以
字节[]
的形式返回文件的全部内容:

public static byte[] readFile(final String filePath) throws IOException {
    final InputStream inputStream = new FileInputStream(filePath);
    ...
}

这个函数无法“处理”不存在的文件;如果
newfileinputstream(filePath)
引发
FileNotFoundException
(它是
IOException
的子类型),则此函数可以做的最好的事情就是通知其调用者。调用者有更多关于
文件路径
从何而来的信息,以及如果文件丢失意味着什么;例如,如果用户键入了
filePath
,那么这可能意味着程序需要向用户显示一条消息,让用户知道可能的键入错误。关键是,
readFile
没有这些信息,因此无法做出正确的决定。因此,它应该让异常向上传播到可以的调用方。

有时,由于许多原因(服务、Restfull api等),让异常向上滚动堆栈是有帮助的。假设您有一个显示或解析文件的方法,并将文件名作为参数,您不知道谁将使用您的方法,也不知道为什么。因此,通过抛出一个异常,您给了开发人员另一个机会来显示其消息或按他希望的方式处理它

try-catch-finally
块的全部目的似乎是处理一个异常,该异常未经处理会使程序崩溃,对吗

不完全是。异常并不总是导致程序崩溃,它可能“只是”导致程序的某些部分无法正常工作。确实,
try catch finally
用于处理异常

为什么要让异常回滚到调用堆栈,以尝试捕获链上的某个位置?价值是什么

因为有时异常发生的方法不适合决定如何处理它

我将给出一个示例:看看方法
Integer.parseInt(strings)
,它获取一个
String
,并尝试根据其内容将其转换为
int
。因为这是在运行时完成的,而且你不能提前知道字符串是什么,所以你必须考虑字符串不是数字,如果它来自用户输入。如果它不是可解析字符串,您希望该方法如何处理它?为什么它要决定一个不是设计用来执行的手术的结果

这就是该方法抛出错误的原因。调用该方法的人有权决定应该做什么,因为该方法只用于将字符串转换为数字。它可以因为最后一个字符串无效而请求一个新字符串,或者只使用默认数字作为占位符

现实生活中的一个类比:老板告诉他的秘书在给定日期安排与员工的会面,秘书发现员工在该日期休假。局长应否自行处理?可能不会。相反,他们会按照“无效会议时间”的思路向老板“抛出一个例外”,让老板决定做什么

在我看来,让异常在链上滚动,而不是立即处理它,只会损害程序,并且是不好的形式,导致效率低下或效率低下

这就是为什么调用范围负责正确地委托事件。要么自己处理,要么向上传递,直到有东西处理


更多信息请参见。

如果
MethC
没有正确处理异常的选项,那么它应该传播到它的调用方法,以便它能够处理它。例如,通过记录异常或使用UI向用户显示通知。这最终会得到更好的代码。MethC的唯一职责是使用I/O操作来做一些事情,它不应该关心打开日志文件或