1. Java异常简析
在程序运行过程中出现的错误,称为异常,异常就是程序运行过程中出现了不正常现象导致程序的中断,在Java中,把各种异常现象进行了抽象形成了异常类,如下图所示:
提醒:此处
RuntimeException
下的 7 个常见异常需要熟练掌握,避免滥用自定义异常!
这里着重强调:
Error
程序无法处理的错误,表示运行应用程序中较严重问题,一般是 JVM 出现的问题,此类异常发生时,JVM 一般会将线程终止Exception
此类属于编译异常,必须编写处理的异常“方案”RuntimeException
此类属于运行时异常,是程序运行时产生的,程序编写者可以编写代码对其进行处理,也可对其抛出或不处理
2. 处理异常的关键字
关键字 | 作用及用法 |
---|---|
try[(resource)]{work;} | 可能抛出异常的代码放在 try 块内,当 try 块内发生异常时,异常会被抛出,若存在 (resource) 在 try 代码块结束后会自动调用 resource.close() 方法(Java 7之后) |
catch(Exception e) | 捕获异常 e ; catch 用来捕获 try 语句块中发生的异常,可以声明多个 catch,catch 里也可以捕捉多个异常 |
finally | finally 语句块总会被执行,一般用于释放资源 |
throw | 用于抛出异常(方法体内) |
throws | 声明该方法可能抛出的异常(方法声明) |
注:
[ ]
为可省略内容
特别地:
- 若在 catch 块中有 return 语句,则会先执行 finally 块的内容再执行 catch 块的返回语句,举个例子:该代码返回值是 3
public int getNum() {
try {
int a = 1 / 0;
return 1;
} catch (Exception e) {
return 2;
} finally {
return 3;
}
}
- 若 finally 中没有 return 语句,但是改变了要返回的值,若是引用类型则会改变,若是基本数据类型或字符串,则不改变
3. 异常的捕获及抛出
此部分忽略了自定义异常部分内容,将放在
SpringBoot
自定义异常部分细说
在定义方法时,如果方法体中有编译时异常需要预处理,可以捕获处理,也可以抛出处理
捕获异常注意事项
- 一般按照由小到大的顺序,也就是先截获子异常,再截获父异常
- 错误范例:
FileNotFoundException
是IOException
的子类,需要放在后面,修改方法是将两个 catch 块交换位置
try{
FileInputStream fis = new FileInputStream("test.txt");
fis.close();
}catch(IOException e){
e.printStackTrace();
}catch(FileNotFoundException e){
e.printStackTrace();
}
- 不要捕获
Throwable
类,因为Throwable
是Error
和Exception
的超类,系统级别错误,一般不应捕捉处理
抛出异常注意事项
子类方法的异常要比父类方法的异常更小
- 如果父类方法没有抛出异常,子类重写后也不能抛出异常
- 如果父类方法抛出了异常,子类方法可以抛出相同的异常,也可以抛出父类异常的子异常,也可以不抛出异常
4. 异常信息的获取
getMessage()
获取异常描述信息,用于打印日志getCause()
获取异常的形成原因,如果是根异常则返回 nullprintStackTrace()
取得异常的堆栈信息,用于调试阶段
注意事项
如果抛出异常的方法使用了JDK动态代理或反射的方法进行执行,所有异常均会被 InvocationTargetException
所覆盖,此时需要抓取异常链获取根异常,下面给出代码模板,此方法同时适用于有在异常链不同位置均需要进行处理的情况
public static List<Throwable> getThrowableList(Throwable throwable) {
ArrayList<Throwable> list;
for(list = new ArrayList<>(); throwable != null && !list.contains(throwable); throwable = throwable.getCause()) {
list.add(throwable);
}
return list;
}
public static Throwable getRootCause(Throwable throwable) {
List<Throwable> list = getThrowableList(throwable);
return list.isEmpty() ? null : list.get(list.size() - 1);
}