04 异常处理
异常
异常分为 Exception 和 Error,其继承关系如下
TODO: Insert inheritance image
Exception 是可以被处理的异常,如NullPointerException
或IllegalArgumentException
;Error 是不一定能被处理的异常,如OutOfMemoryError
,NoClassDefFoundError
如果 Exception 没有被处理,那么程序无法被编译。
方法可以通过throw
关键词表示调用方法时可能抛出的异常,如String.getBytes(String)
的签名
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
...
}
在调用String.getBytes(String)
时,必须使用一个 try-catch 块处理UnsupportedEncodingException
。
不过如果在另一个被标记为throws UnsupportedEncodingException
的方法里调用String.getBytes(String)
,我们就不需要处理异常。异常处理会被下放到调用该方法的其他方法。最坏情况我们必须要在main
方法里处理该异常,除非main
也被标记为throws UnsupportedEncodingException
。如
在处理异常时,我们可以使用printStackTrace()
打印异常栈,如
try {
// ...
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try-catch 语句
多个 catch 语句按顺序分别处理不同异常
使用catch (ExceptionA | ExceptionB)
同时处理多个异常
使用 finally 语句,无论异常是否发生,都在最后执行特定逻辑,如清理资源
抛出异常
使用throw
关键词抛出异常
自定义异常
在大型项目中,我们会定义一套异常继承体系。
首先自定义一个BaseException
,然后继承这一根异常,定义其他异常。
BaseException
本身通常继承自RuntimeException
。
NullPointerException
(NPE)
为避免 NPE,可以
使用空数据,而非
null
。例如,返回一个空数组,或空字符串使用
Optional<T>
断言
assert
日志(log)
Java.util.logging
Common Logging
Log4j
SLF4J 和 Logback
杂项
- 如果 catch 和 finally 都抛出了异常,只有 finally 的异常会被处理,catch 的异常会被屏蔽(Suppressed Exception)。不推荐这么做。