1.首先讲一下Java异常体系
Java中异常中常遇到的哪些坑
1.第一个坑 在finally中进行返回,此时的返回值会覆盖正常的返回值
具体代码如下
public static int getReturn() {
int a = 2;
int b = 10;
try {
return ++a;
} finally {
return ++b;
}
}
第二个坑,在spring的事物中,捕获了异常,却没有抛出去,导致事物无法回滚
具体代码如下:
@Transaction(rollbackFor=Exception.class)
public void addUserInfo(UserInfoDTO userInfoDTO){
try{
//do some thing
insertDB();
//do something
}cache(Exception){
log.error(“新增用户信息异常:”,e)
}
}
正确流程: 在事物中捕获异常,要么手动回滚,要么继续往上抛
第三个坑,在Java中加锁的时,加锁异常,导致错误直接异常被覆盖,增加排查问题成本具体代码如下: public static void main(String[] args) {
Lock lock = new ReentrantLock();
try{
//有可能加锁失败
lock.lock();
}
finally {
lock.unlock();
}
}
由于lock.lock可能失败,这个时候会执行 lock.unlock导致抛IllegalMonitorStateException 会对第一个异常进行覆盖 正确流程: 把加锁操作放到 try 外面
什么是异常链?
捕获一个异常后抛出另一个异常,并且把原始异常信息保存下来,这被称为异常链
public static void main(String[] args) {
try {
methodTwo();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void methodTwo() throws IOException{
try{
methodThree();
}catch (ClassNotFoundException e){
throw new IOException("method tow error",e);
}
}
public static void methodThree() throws ClassNotFoundException {
try{
if(true){
throw new IOException();
}
}catch (IOException e){
throw new ClassNotFoundException("method three error:",e);
}
java.io.IOException: method tow error
at mc.longyi.exception.ExceptionChain.methodTwo(ExceptionChain.java:32)
at mc.longyi.exception.ExceptionChain.main(ExceptionChain.java:21)
Caused by: java.lang.ClassNotFoundException: method three error:
at mc.longyi.exception.ExceptionChain.methodThree(ExceptionChain.java:43)
at mc.longyi.exception.ExceptionChain.methodTwo(ExceptionChain.java:30)
... 1 more
Caused by: java.io.IOException
at mc.longyi.exception.ExceptionChain.methodThree(ExceptionChain.java:40)
... 2 more
异常链的作用
可以将异常进行传递,方便我们在排查问题的时候,能找到引发问题的原因,避免异常信息丢失
自定义异常:
public class BizException extends Exception{
private String message;
private Throwable throwable;
public BizException(String message){
super(message);
this.message=super;
}
public BizException(String message,Throwable throwable){
super(message,throwable);
this.message=message;
this.throwable=throwable;
}
}
处理异常最佳实践
一:当需要向上抛出异常的时候,需根据当前业务场景定义具有业务含义的异常,优先使用行业内定义的异常或者团队内部定义好的。例如在使用dubbo进行远程服务调用超时的时候会抛出DubboTimeoutException,而不是直接把RuntimeException抛出
二:请勿在finally代码块中使用return语句,避免返回值的判断变得复杂
三:捕获异常具体的子类,而不是Exception,更不是throwable。这样会捕获所有的错误,包括JVM抛出的无法处理的严重错误。
四:不要使用异常当作控制流程来使用
五:清理资源,释放连接等操作一定要放在finally代码块中,防止内存泄漏,如果finally块处理的逻辑比较多且模块化,我们可以封装成工具方法调用,代码会比较简洁