try catch 肯定可以嵌套的,可以先来个嵌套小测试。
public static void main(String[] args) {
try {
System.out.println("**********************外层try**********************");
errorMethod();
} catch (Exception e) {
System.out.println("**********************外层catch" + e + "**********************");
} finally {
System.out.println("**********************外层finally**********************");
}
}
private static void errorMethod() {
try {
System.out.println("**********************内层try**********************");
int i = 0;
int a = 100 / i;
} catch (Exception e) {
System.out.println("**********************内层catch" + e + "**********************");
} finally {
System.out.println("**********************内层finally**********************");
}
}
内层函数体用零作被除数,报ArithmeticException。
若是注释掉内层catch,其他一样:
private static void errorMethod() {
try {
System.out.println("**********************内层try**********************");
int i = 0;
int a = 100 / i;
} /*catch (Exception e) {
System.out.println("**********************内层catch" + e + "**********************");
}*/ finally {
System.out.println("**********************内层finally**********************");
}
}
运行结果是:
try catch 嵌套内层catch 可以捕获异常时,外层catch不会执行,但finally (多用于IO关闭)都会执行。
总结一个报错后的执行顺序:
try {
//A 报错地方
try {
//B
} catch (Exception e) {
//C
} finally {
//D
}
//E
} catch (Exception e) {
//F
} finally {
//G
}
执行顺序:
网上很多争论这个,感兴趣读者可以看这里:https://hllvm-group.iteye.com/group/topic/27001
结论是:
语义不同的东西是不适合用来比较性能的。
但如果需求逻辑允许,把循环放在 try/catch 内会比把 try/catch 放在循环内要更有机会得到更好的优化。因为一般循环是重点优化对象,如果循环内部的控制流比较简单的话,分析和优化就会比较方便;把循环放在try/catch里面的话,就循环自己来看内部的控制流会比反过来放要简单一些。
抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常。
throw: 一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。
throws:是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
如:
if (httpResponse != null) {
if (httpResponse.getStatusCode() == HttpStatus.SC_OK) {
Result result = JSON.parseObject(httpResponse.getResult(), Result.class);
log.info("远程调用返回[result]={}", result);
}else {
log.warn("远程调用接口httpResponse返回异常码 : [url]={}, [httpResponse]={}", notifyUrl, httpResponse);
throw new Exception("远程调用接口httpResponse返回异常码");
}
}else {
log.warn("远程调用接口返回空HttpResponse: [url]={} ", notifyUrl);
throw new Exception("远程调用接口返回空HttpResponse");
}
这时候若是想在本方法内处理异常,则需要try catch 包住这段代码,若是不想处理,则抛出到上层处理,需在该方法后添加 throws Exception,如:
public void asyncDevStatusTes(List deviceIdList,Integer opeStatus) throws Exception{
...
}
基础过后,说下我遇到的问题和解决办法:
在用异步线程池的时候,需要被调用函数向上层抛出异常,用 @Async注解后,调用函数捕获不到异常。而且 spring事务回滚也不起作用,都去掉异步注解后才能解决。原因是异步线程池会启用多个Task,这样事务里面的数据库操作 就不是一个任务了,事务不起作用。
至于书写异常可能会碰到的错误:Unhandled exception: Java.lang.exception
优质文章:try catch 的正确使用
参考文章:throw、throws