一.概述
- 本文说明Java中finally的用法和可能遇到的坑
- finally的目的是保证代码被执行,但也会存在不执行的情况
- finally 代码块的原理是复制 finally 代码块的内容,分别放在 try-catch 代码块所有正常执行路径以及异常执行路径的出口中。
所以不管是是正常还是异常执行,finally都是最后执行的。
二. finally会执行的情况
1.有catch(无异常)
try {
System.out.println("try execute");
} catch (RuntimeException e) {
System.out.println("catch execute");
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
3.有catch(try异常)
try {
System.out.println("try execute");
throw new RuntimeException("try Exception");
} catch (Exception e) {
System.out.println("catch execute");
} finally {
System.out.println("finally execute");
}
输出
try execute
catch execute
finally execute
4.有catch(catch异常)
try {
System.out.println("try execute");
} catch (Exception e) {
System.out.println("catch execute");
throw new RuntimeException("catch Exception");
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
5.有catch(try/catch都异常)(会抛出异常)
try {
System.out.println("try execute");
throw new RuntimeException("try Exception");
} catch (Exception e) {
System.out.println("catch execute");
throw new RuntimeException("catch Exception");
} finally {
System.out.println("finally execute");
}
输出
try execute
catch execute
finally execute
Exception in thread "main" RuntimeException: catch Exception
6. 没有catch(无异常)
try {
System.out.println("try execute");
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
7. 没有catch(try异常)(会抛出异常)
try {
System.out.println("try execute");
throw new RuntimeException("try Exception");
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
Exception in thread "main" ServiceException: try Exception
8. 有返回值(try)(程序返回"try return")
try {
System.out.println("try execute");
return "try return";
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
9. 有返回值(catch)(程序返回"catch return")
try {
System.out.println("try execute");
throw new RuntimeException("try exception");
} catch (Exception ex) {
return "catch return";
} finally {
System.out.println("finally execute");
}
输出
try execute
finally execute
三. finally不会执行的情况
1. 调用 System.exit 函数
try {
System.out.println("try execute");
System.exit(1);
} catch (Exception ex) {
System.out.println("catch execute");
} finally {
System.out.println("finally execute");
}
输出
try execute
2. 调用 halt 函数
try {
System.out.println("try execute");
Runtime.getRuntime().halt(1);
} catch (Exception ex) {
System.out.println("catch execute");
} finally {
System.out.println("finally execute");
}
输出
try execute
四. 常见问题
1. 忽略异常(程序返回"finally return")
try {
System.out.println("try execute");
throw new RuntimeException("try exception");
} finally {
System.out.println("finally execute");
return "finally return";
}
输出
try execute
finally execute
2. finally存在return语句,则 try 和 catch 存在的返回语句就会被忽略(程序返回"finally return")
try {
System.out.println("try execute");
return "try return";
} finally {
System.out.println("finally execute");
return "finally return";
}
输出
try execute
finally execute
3. finally抛异常(不会有返回值,一直抛出异常 RuntimeException)
try {
System.out.println("try execute");
return "try return";
} finally {
System.out.println("finally execute");
throw new RuntimeException("finally exception");
}
输出
try execute
finally execute
Exception in thread "main" java.lang.RuntimeException: finally exception
4. finally异常覆盖try异常
try {
System.out.println("try execute");
throw new RuntimeException("try exception");
} finally {
System.out.println("finally execute");
throw new RuntimeException("finally exception");
}
输出
try execute
finally execute
Exception in thread "main" java.lang.RuntimeException: finally exception
5. finally异常覆盖catch异常
try {
System.out.println("try execute");
throw new RuntimeException("try exception");
} catch (Exception ex) {
System.out.println("catch execute");
throw new RuntimeException("catch exception");
} finally {
System.out.println("finally execute");
throw new RuntimeException("finally exception");
}
输出
Exception in thread "main" java.lang.RuntimeException: finally exception
try execute
catch execute
finally execute
6. finally异常覆盖其它异常原因及解决
原因:一个方法只能抛出一种异常,无法出现两种
解决1:finally代码块自行捕获和处理异常
try {
System.out.println("try execute");
} finally {
System.out.println("finally execute");
try {
throw new RuntimeException("finally exception");
} catch (Exception ex) {
log.error(ex.getMessage());
}
}
输出
try execute
finally execute
错误日志:finally exception
解决2:异常追加
Exception e = null;
try {
System.out.println("try execute");
throw new RuntimeException("try exception");
} catch (Exception ex) {
System.out.println("catch execute");
e = ex;
} finally {
System.out.println("finally execute");
try {
throw new RuntimeException("finally exception");
} catch (Exception ex) {
if (e != null) {
e.addSuppressed(ex);
} else {
e = ex;
}
}
}
throw e;
输出
try execute
catch execute
finally execute
Exception in thread "main" java.lang.RuntimeException: try exception
Suppressed: java.lang.RuntimeException: finally exception