Java 捕获已检查的异常后重新引发RuntimeException
在Java中,可以观察到有一种惯例,即在处理Java 捕获已检查的异常后重新引发RuntimeException,java,exception,exception-handling,Java,Exception,Exception Handling,在Java中,可以观察到有一种惯例,即在处理选中的异常之后重新抛出运行时异常 这种方式既有好的后果,也有坏的后果。当编译器通过检查异常强制处理某些内容时,开发人员只需捕获它并将其作为运行时异常重新抛出即可将其清除 有人能解释一下这种情况是否是一种好的做法吗?如果是这样的话,这种方法会不会更不容易出错,或者会使代码库不稳定?事实上,正是在处理已检查异常时的无能尝试导致了代码库不稳定。通常情况下,您会遇到以下问题: try { //stuff } catch (IOException e) {
选中的异常之后重新抛出运行时异常
这种方式既有好的后果,也有坏的后果。当编译器通过检查异常
强制处理某些内容时,开发人员只需捕获它并将其作为运行时异常
重新抛出即可将其清除
有人能解释一下这种情况是否是一种好的做法吗?如果是这样的话,这种方法会不会更不容易出错,或者会使代码库不稳定?事实上,正是在处理已检查异常时的无能尝试导致了代码库不稳定。通常情况下,您会遇到以下问题:
try {
//stuff
} catch (IOException e) {
log.error("Failed to do stuff", e);
throw e;
}
然后再上一层,您将不得不再次处理它,通常会将其全部记录下来,并将日志文件弄得一团糟。如果你不改口,情况会更糟:
try {
// do stuff
} catch (IOException e) {
return null;
}
现在调用代码不知道出了什么问题,更不用说什么了。与这些尝试相比,这实际上完全满足了应用程序逻辑的需要:
try {
// do stuff
} catch (IOException e) {
throw new RuntimeException(e);
}
现在,异常可以自由地向上传播调用堆栈,直到它到达定义良好的异常屏障,在该屏障中:
中止当前工作单元李>
在一个统一的地点记录
简言之,要决定是抓住并处理,还是抓住并重新抓捕,只需问自己以下问题:
发生此异常是否必须中止当前工作单元
- 如果是:重新显示未检查的异常李>
- 如果否:在catch块中提供有意义的恢复代码。(否,日志记录不是恢复)
根据多年的实际经验,我可以告诉您,所有可能检查的异常中有90%以上属于“中止”类型,不需要在发生地进行处理
反对已检查异常的语言功能的参数
如今,检查异常被广泛认为是语言设计中的一个失败实验,以下是关键论点:
API创建者不能在客户端代码中决定其异常的语义
Java的推理是,异常可以分为
编程错误导致的异常(未选中)李>
由程序员无法控制的情况引起的异常(已检查)
虽然这种划分在某种程度上可能是真实的,但它只能从客户机代码的角度进行定义。更重要的是,这在实践中并不是一个非常相关的划分:真正重要的是在什么时候必须处理例外。如果要在异常屏障处延迟处理,则检查的异常不会获得任何结果。如果及早处理,那么只有在某些情况下,检查异常才会带来轻微的收益
实践已经证实,被检查的异常所带来的任何收益与对实际项目造成的实际损害相比都相形见绌,每个Java专业人员都见证了这一点。Eclipse和其他IDE也是罪魁祸首,它们建议没有经验的开发人员将代码包装在try-catch中,然后考虑在catch块中编写什么
每当您遇到抛出异常的方法时,您都会发现另一个活生生的证据,证明检查异常的不足。在这种情况下,术语“可以摆脱它”并不完全正确。这就是消除异常:
try {
} catch (Exception e){
e.printStacktrace();
}
这是try-catch
使用中最常见的错误做法。您正在捕获异常,然后打印它。在这种情况下,catch块捕获异常并将其打印出来,而程序在catch块之后继续执行,就好像什么都没有发生一样
当您决定捕获块而不是抛出异常时,您必须能够管理异常。有时异常是不可管理的,必须抛出异常
这是你应该记住的:
如果客户端可以采取其他操作从
异常,将其设置为选中的异常。如果客户不能这样做
任何有用的内容,然后取消选中异常。我是说有用
采取步骤从异常中恢复,而不仅仅是记录
例外
如果你不打算做一些有用的事情,那么就不要抓住例外。作为RuntimeException重新抛出它有一个原因:如前所述,程序无法继续,因为什么都没有发生。这样,一个好的做法是:
try {
} catch (Exception e){
//try to do something useful
throw new RuntimeException(e);
}
这意味着:您刚刚捕获了一个异常(如SQLException
),如果不停止并重置线程,就无法从中恢复。您捕获它,尝试在两者之间进行一些操作(如重置某些内容、关闭打开的套接字等),然后抛出一个RuntimeException()
RuntimeException将挂起整个线程,避免程序继续运行,就像什么都没有发生一样。此外,您还可以在不打印的情况下管理另一个异常。检查异常的概念是“仅限Java”-据我所知,Java采用此概念后没有任何语言
捕获的已检查异常太多。。。然后默默地忽略了
如果你看看Scala,他们也放弃了它——它只是为了Java兼容性
在Oracle网站上的这篇文章中,您可以找到以下定义:
如果可以合理预期客户机从异常中恢复,则将其设置为已检查异常。
如果客户端无法从异常中恢复,请将其设置为未检查的异常
Scala也采用了这个概念,而且效果很好
从技术上讲,你的建议是可行的。无论哪种方式,都需要进行规程和代码审查。根据上下文的不同,这可能是好的,也可能是不好的,但可能不是
根据经验,运行时异常只能用于