Java异常throws和throw区别都没搞懂,面试感觉很慌啊

程序员、Java后端、面试题、异常类型、日志

吐槽

最近看公司业务代码发现异常那块天天用,但理解不深啊

赶紧复习下,我还是有一颗学习的心

互联网项目一个异常、一个日志都非常重要,设计的不好后果很痛苦。

Java异常throws和throw区别都没搞懂,面试感觉很慌啊

异常类型

Throwable有两个子类,Error和Exception

Checked Exception

Unchecked Exception

基本概念扫盲

  • 异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。
  • Error也是unchecked exception,也是无法预先处理的。
  • 所有checked exception都是需要在代码中处理的,它们的发生是可以预测的

check异常

如Exception /IOException

uncheck异常

RuntimeException及他的子类

check异常总结

  1. 编译保证,没catch或throws编译报错
  2. throw的是check异常就当前方法必须 throws Exception 或catch 住
  3. throw的是check异常throws Exception这个异常了,上层方法必须 catch

uncheck异常总结

  • 公司的自定义异常类都是基础RuntimeException,然后配合异常枚举
  • com.google.common.base.Preconditions#checkArgument(boolean, java.lang.Object) 公司大佬喜欢用这个异常工具,自己可以参考造一个出来

异常理解

编译错误案例代码

public static void throwChecked(int a)
{
 if (a > 0)
 {
 //自行抛出Exception异常
 //该代码必须处于try块里,或处于带throws声明的方法中
 throw new Exception("a的值大于0,不符合要求");
 }
}

idea 会提示 :Unhandled exception: java.lang.Exception

正常异常案例代码

public static void throwChecked(int a)throws Exception
{
 if (a > 0)
 {
 //自行抛出Exception异常
 //该代码必须处于try块里,或处于带throws声明的方法中
 throw new Exception("a的值大于0,不符合要求");
 }
}

企业自定义异常类

优秀IT企业里不是创建一堆自定义异常,而是异常类配合异常枚举来设计

一般业务系统自定义异常类不要少过3个

get/set方法我就省略了

public class WangException extends RuntimeException {
 /**错误码*/
 private WangErrorCodeEnum errorCode;
 /**详细错误信息*/
 private Map errorMap = new HashMap();
 /**
 * 带参构造器.
 * @param errorCode
 */
 public WangException(WangErrorCodeEnum errorCode) {
 super(errorCode.getDesc());
 this.setErrorCode(errorCode);
 }
 /**
 * 带参构造器
 */
 public WangException(WangErrorCodeEnum errorCode, String message) {
 super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
 this.setErrorCode(errorCode);
 }
 /**
 * 带参构造器.
 * @param errorCode
 * @param errorContext
 */
 public WangException(WangErrorCodeEnum errorCode, ErrorContext errorContext) {
 this(errorCode, findMessage(errorContext));
 }
 /**
 * 带参构造器.
 * @param errorCode
 * @param errorMap
 */
 public WangException(WangErrorCodeEnum errorCode, Map errorMap) {
 this(errorCode);
 this.errorMap = errorMap;
 }
 /**
 * 带参构造器.
 * @param errorCode
 * @param message
 */
 public WangException(WangErrorCodeEnum errorCode, String message, Map errorMap) {
 super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
 this.setErrorCode(errorCode);
 this.errorMap = errorMap;
 }
 /**
 * 带参构造器.
 *
 * @param message
 */
 public WangException(String message) {
 super(message);
 this.setErrorCode(WangErrorCodeEnum.UNKNOWN_SYS_ERROR);
 }

错误枚举

public enum WangErrorCodeEnum {
 SYS_ERROR("SYS_ERROR", "系统错误,请重试"),
 UNKNOWN_SYS_ERROR("UNKNOWN_SYS_ERROR", "未知的系统异常"),

高级点的异常枚举

有日志级别、是系统还是业务异常、日志是error还是warn、info等等

SYSTEM_ERROR("000", ErrorLevels.ERROR,
 ErrorTypes.SYSTEM, "系统异常"),

模板模式

异常从dao、service等等抛上来后,

需要把异常信息转换封装返回给前端、或rpc调用端等等

这里一般可以采用模板模式,把各种异常的catch 转换封装

业务代码里只要调用模板代码即可,什么异常转换、日志记录都统一管理,

业务代码干净多了,技术经理看到又可以加工资了

日志规范

生产上尽量把info、error、warn分清楚

切记不要都打到error里面了(很多公司对error非常敏感的)

异常日志打印尽量把 场景、异常具体原因、影响业务等等打清楚,

异常码异常描述尽量精细

大型分布式项目中日志好不好

决定了下班早不早,

平时写业务代码习惯打印“其他异常”,生产出故障了就发现自己是多么的坑爹

分布式trace_id非常强大,后边我研究下整理整理

这就是我知道的异常设计最优雅的案例,程序员专家可以告诉我更优雅的


分享到:


相關文章: