编程后端开发人员

在Java中,检查异常和未检查异常有何区别,如何正确设计错误处理,以及在使用它们时应避免哪些错误?

用 Hintsage AI 助手通过面试

答案

在Java中,异常分为检查异常(checked)和未检查异常(unchecked)。

  • 检查异常—— 继承自Exception,但不继承自RuntimeException。编译器要求显式处理这些异常,使用try-catch或者在throws中声明。
  • 未检查异常—— 继承自RuntimeException。编译器不要求强制处理这些异常。
public void readFile(String file) throws IOException { /* ... */ } // checked public void divide(int a, int b) { int res = a/b; } // unchecked (ArithmeticException)

主要的区别是——检查异常用于可预期的、可恢复的情况(例如,输入输出错误),而未检查异常用于程序逻辑错误或无法恢复的严重情况(例如,NullPointerException)。

难题问题

问题: 如果您的方法可能抛出未检查异常,是否需要处理或在throws中声明?

答案: 不需要。编译器不要求检查或声明不可恢复(unchecked)异常。这些异常的处理由您自行决定;可以使用try-catch,但通常情况是让其“崩溃”,一直到全局处理程序。

public void foo() { throw new IllegalArgumentException(); } // 不需要处理或声明

由于不了解主题细节而导致的实际错误示例


故事

在一个银行API项目中,在处理输入输出错误时抛出了RuntimeException而不是检查异常。因此,客户没有被迫处理这些异常,导致在失去与服务器的连接时程序错误,应用程序“崩溃”而未告知用户。


故事

开发人员在方法签名中声明了多余的throws Exception(例如,数据库),导致所有使用的方法都被迫使用try-catch或也需throws。这使代码变得混乱,降低了可读性,并且使重构变得困难。


故事

在其中一个微服务中,捕获了所有异常,使用了通用catch (Exception e)。这也捕获了未检查异常(例如,NullPointerException),导致严重错误被“安静地”忽略——服务处理了不正确的数据。