捕获Checked Exceptions后重新抛出RuntimeExceptions

MCF*_*MCF 13 java exception-handling exception

在Java中,观察到有一种RuntimeException在处理之后重新抛出一个公约Checked Exception.

这种方式有好的和坏的后果.当编译器强制要通过a处理某些东西时Checked Exception,开发人员可以通过捕获它并将其重新抛出来摆脱它RuntimeException.

有人可以解释这种情况是否可以被认为是一种好的做法?如果是这样,这种方法会不会出错,还是会使代码库不稳定?

Mar*_*nik 19

实际上,处理检查异常导致代码库不稳定是无能的尝试.通常,你会有这个:

try {
   //stuff
} catch (IOException e) {
   log.error("Failed to do stuff", e);
   throw e;
}
Run Code Online (Sandbox Code Playgroud)

然后再下一级,你将不得不再次处理它,通常记录它并弄乱日志文件.如果不重新抛出,情况会更糟:

try {
   // do stuff
} catch (IOException e) {
  return null;
}
Run Code Online (Sandbox Code Playgroud)

现在调用代码不知道出了什么问题,更不用说是什么了.与这些尝试相比,这实际上完成了应用程序逻辑所需的内容:

try {
  // do stuff
} catch (IOException e) {
  throw new RuntimeException(e);
}
Run Code Online (Sandbox Code Playgroud)

现在,异常可以自由地向上传播调用堆栈,直到它到达明确定义的异常障碍,其中:

  1. 中止目前的工作单位;
  2. 记录在一个统一的点上.

简而言之,要决定是抓捕还是抓住并重新抛出,只要问自己这个问题:

此异常的发生是否必须中止当前的工作单元?

  • 如果:重新抛出未经检查的异常;
  • 如果:在catch-block中提供有意义的恢复代码.(不,日志记录不是恢复).

根据多年的实际经验,我可以告诉您,超过90%的所有可能检查的异常都属于"中止"类型,并且不需要在发生的地方进行处理.

针对已检查异常的语言特征的争论

今天,被检查的异常被广泛认为是语言设计中失败的实验,简而言之,这是关键的论点:

API创建者无法在客户端代码中决定其异常的语义.

Java的推理是异常可以分为

  1. 编程错误导致的异常(未选中);
  2. 由程序员控制之外的情况引起的异常(选中).

虽然这种划分在某种程度上可能是真实的,但它只能从客户端代码的角度来定义.更重要的是,它在实践中并不是一个非常相关的部门:真正重要的是在什么时候必须处理例外.如果要处理延迟,则在异常屏障处,检查异常不会获得任何结果.如果提前处理,那么有时只有经过检查的例外会有轻微的收益.

实践已经证实,经过检查的例外所带来的任何收益都与现实生活项目的实际损害相比相形见绌,正如每位Java专业人士所见证的那样.Eclipse和其他IDE也应该受到指责,建议没有经验的开发人员将代码包装在try-catch中,然后想知道在catch块中写什么.

无论何时遇到一种方法throws Exception,你都找到了另一种生活证据,证明了检查异常的不足.

  • @devconsole如果你的建议被遵循,它将以声明`throws Exception`的所有接口方法结束.没有人知道底层实现可能会抛出什么.在语义层面,`throws Exception`与没有`throws`子句的内容完全相同. (6认同)
  • @Pablo-要检查异常是否在调用堆栈中传播,还意味着您需要使用“ throws”声明所有函数,这很快会使您的代码混乱。一种更干净的方法是将其转换为未经检查的异常,并在您感兴趣的地方捕获它。看一下鲍勃·马丁斯(Bob Martins)的书(清洁代码-http://www.amazon.co.uk/dp/0132350882/?tag=hydra0b-21&hvadid=9550951749&ref=asc_df_0132350882)。 (2认同)