Java 异常体系
Exception
Exception 异常体系就是在 return
语句之外为方法提供另外一种出口
-
Throwable
=> checked exception => 可以被抛出的东西 => 有毒 -
Exception
=> checked exception => 受检异常 => 有毒 => 预料之内的异常 => 需要对预料之内的异常进行处理 =>IOException
=> 可以恢复 -
RuntimeException
=> unchecked exception => 运行时异常,无毒 => 意料之外的 => Bug => 不需要声明 -
Error
=> unchecked exception => 错误,无毒 => 不能恢复的异常
try catch finally
- 在栈帧中一旦碰到
throw
它会结束当前栈帧,如果没有try
,异常将击穿所有栈帧,直到遇到try catch
-
try catch finally
中的finally
无论什么情况都会被执行,即使try
|catch
中有return
-
finally
块中不建议写return
语句,finally
块中最好的实践是执行资源的清理工作 -
catch
中做的事情- 处理异常
- 在日志里打印异常
- 返回对应的对异常的处理
-
try-with-resources
=> JDK 7+ =>try(content) {}
=>content
会在finally
中自动的 close => 隐式的finally
=>
content 必须实现AutoCloseable
interface
throw vs throws
- throw => 抛出一个
Throwable
,终止方法当前的操作 - throws => 只是一个声明 => 表示一个方法可能会抛出一个异常 => 后果:任何调用了它的方法都有被迫在自己的方法签名上丢一个
throws
语句或者加try catch
catch 的级联与合并
级联
public static void main(String[] args) {
try{
throwCheckedException();
} catch (FileNotFoundException e) {
System.out.println("文件没找到");
} catch (EOFException e) {
System.out.println("文件已到达末尾");
} catch (Exception e) {
e.printStackTrace();
}
}
catch
错误的顺序按照从小到大的顺序排列
合并
Java 7+ 才有合并
public static void main(String[] args) {
try{
throwCheckedException();
} catch (NullPointerException | IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalStateException | IllegalArgumentException e) {
// 做点别的事情
}
}
栈轨迹 & 异常链
- StackTrace => 栈轨迹
- Caused by => 异常链
排查问题最重要的信息,没有之一
class TestException {
public static void main(String[] args) {
try {
processUserData();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void processUserData() {
int userId = 1;
try {
insetIntoDatabase();
} catch (SQLException e) {
throw new UserAlreadyExistException("插入 id 为" + userId + "的数据的时候发生了异常", e);
}
}
private static void insetIntoDatabase() throws SQLException {
throw new SQLException("重复的键值");
}
}
class UserAlreadyExistException extends RuntimeException {
public UserAlreadyExistException(String message, Throwable cause) {
super(message, cause);
}
}
Stack Trace & Caused by
异常抛出原则
- 能用
if else
处理的,不要使用异常(try catch
)- 无法保证
catch
到的异常一定是想抓到的,可能错误的catch
到了更深层次的异常 - 相比于正常的
if
判断,异常的创建是非常,非常昂贵的操作
- 无法保证
- 尽早抛出异常 => 如果可以处理异常,则处理,如果处理不了,要立刻抛出这个异常
- 异常要准确,带有详细信息
- 抛出异常也比悄悄的执行错误的逻辑强的多
异常的处理原则
- 本方法是否有责任处理这个异常? => 不要处理不归自己管的异常
- 本方法是否有能力处理这个异常? => 如果自己无法处理,就抛出
- 如非万分必要,不要忽略异常
try { URLDecoder.decode("", "UTF-8"); } catch (UnsupportedEncodingException ignored) { // 忽略异常 }
JDK 内置异常
NullPointerException
-
ClassNotFoundException
|NoClassDefFoundError
-
IllegalStateException
|IllegalArgumentException
|IllegalAccessException
ClassCastException
知识点
- IOException 通常代表预期之内的异常
网友评论