今天搞懂了两个问题
- check Exception 和 unchecked Exception 的区别
- try-catch和throw,throws的区别
今天遇到一个bug,需要这样处理:Feign调用如果失败了,则不更新数据库
处理feign调用获取返回值的方法是这么写的
package com.common.Util;
import com.alibaba.fastjson.JSON;
import com.common.base.FeignResponse;
import com.common.enums.ErrorCodeEnum;
import com.service.feign.IFunction;
import com.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
@Slf4j
public class FeignUtils {
public static <T, U, C, R> R getData(ErrorCodeEnum errorCode, T t, U u, C c , IFunction<T, U, C, FeignResponse<R>> function) {
FeignResponse<R> response;
try {
response = function.apply(t, u, c);
} catch (Exception e) {
log.error("Feign调用失败, 调用参数:[{}][{}]", JSON.toJSONString(t) ,JSON.toJSONString(u), e);
throw new BusinessException(ErrorCodeEnum.FEIGN_CALL_FAILED.getCode(),"Feign调用失败");
}
return handelResponse(errorCode, response);
}
public static <T, U, R> R getData(ErrorCodeEnum errorCode, T t, U u, BiFunction<T, U, FeignResponse<R>> function) {
FeignResponse<R> response;
try {
response = function.apply(t, u);
} catch (Exception e) {
log.error("Feign调用失败, 调用参数:[{}][{}]", JSON.toJSONString(t) ,JSON.toJSONString(u), e);
throw new BusinessException(ErrorCodeEnum.FEIGN_CALL_FAILED.getCode(),"Feign调用失败");
}
return handelResponse(errorCode, response);
}
public static <T, R> R getData(ErrorCodeEnum errorCode, T param, Function<T, FeignResponse<R>> function) {
FeignResponse<R> response;
try {
response = function.apply(param);
} catch (Exception e) {
log.error("Feign调用失败, 调用参数:[{}]", JSON.toJSONString(param) , e);
throw new BusinessException(errorCode.getCode(),"Feign调用失败", e);
}
return handelResponse(errorCode, response);
}
public static <T, R> R getData(ErrorCodeEnum errorCode, Supplier<FeignResponse<R>> function) {
FeignResponse<R> response;
try {
response = function.get();
} catch (Exception e) {
log.error("Feign调用失败", e);
throw new BusinessException(errorCode.getCode(),"Feign调用失败",e);
}
return handelResponse(errorCode, response);
}
private static <R> R handelResponse(ErrorCodeEnum errorCode, FeignResponse<R> response) {
if (Objects.isNull(response) || !Objects.equals("0", response.getCode())) {
throw new BusinessException(errorCode.getCode(),JSON.toJSONString(response.getMsg()));
}
return response.getData();
}
}
在try中捕获异常,catch中throw异常,调用getData的方法还会继续执行吗?
断点调试直接抛出异常,程序结束
try-catch和throw,throws的区别:
1.throw
throw 就是抛出一个异常,并获取这个异常的引用,这个异常会被抛到外部的环境,由外部环境进行处理
try catch是直接处理,处理完成之后程序继续往下执行,throw则是将异常抛给它的上一级处理,程序便不往下执行了。
2.throws
throws并不是抛出一个实际的Exception而是一个异常声明,它声明这个方法可能会抛出一个异常,注意是可能,所以在没有异常的情况下也是可以用throws的,而throws本身的作用也是用来提高程序的健壮性,反过来,如果这个方法的的确确的有一个异常,那么编译器会强制让你加上throws这个异常声明。
3.try catch
在try块里经常放上可能会抛出异常的程序段
catch恰好就是处理try里抛出来的异常,其中catch的参数列表接收的是一个异常的引用,是throw抛出来的异常的引用,这样我们就可以得到这个异常的对象
总结:在程序中有异常的代码被try catch后,后边的代码能够继续执行,如果是throws 出来的,则运行到异常代码处就会停止执行,抛出异常
写了一段测试代码验证
public static void main(String[] args){ try { a(); } catch (Exception e) { e.printStackTrace(); } System.out.println("s"); } public static void a() { try { int a = 1; int b = a/0; } catch (Exception e) { throw new Exception("Feign调用失败"); } }
上面代码报错:unhandled exception:java.lang.Exception
发现 throw new RuntimeException 不会报错
而 throw new Exception 和 throw new IOException 会报错
如果将测试代码改为如下,则不报错
public static void main(String[] args){ try { a(); } catch (Exception e) { e.printStackTrace(); } System.out.println("s"); } public static void a() throws IOException{ try { int a = 1; int b = a/0; } catch (Exception e) { throw new IOException("Feign调用失败"); } }
或将测试代码改为如下,也不报错
public static void main(String[] args){ try { a(); } catch (Exception e) { e.printStackTrace(); } System.out.println("s"); } public static void a(){ try { int a = 1; int b = a/0; throw new IOException("Feign调用失败"); } catch (Exception e) { } }
因为Exception是check异常,也就是必须在代码层面直接捕获处理的
checked: 一般是指程序不能直接控制的外界情况,是指在编译的时候就需要检查的一类exception,用户程序中必须采用try catch机制处理或者通过throws交由调用者来处理。这类异常,主要指除了Error以及RuntimeException及其子类之外的异常。
unchecked:是指那些不需要在编译的时候就要处理的一类异常。在java体系里,所有的Error以及RuntimeException及其子类都是unchecked异常。再形象直白的理解为不需要try catch 等机制处理的异常,可以认为是unchecked的异常。
+-----------+ | Throwable | +-----------+ / / +-------+ +-----------+ | Error | | Exception | +-------+ +-----------+ / | / | \________/ \______/ +------------------+ unchecked checked | RuntimeException | +------------------+ / | | \_________________/ unchecked