Java自定义异常封装

  • 前言:异常的分类
  • 1.为什么要自定义异常封装?
  • 2.自定义异常封装有哪些优点?
    • 2.1 提高系统的友好性
    • 2.2 提高系统的可维护性
    • 2.3 解决Java异常机制自身的缺陷
  • 3. 如何进行自定义异常封装?

前言:异常的分类

Throwable包含了错误(Error)和异常(Excetion两类)


异常类分为2类:运行时异常(RuntimeException, 又叫非检查异常)和非运行时异常(又叫检查异常)

1.运行时异常都是RuntimeException类及其子类,如 NullPointerException、IndexOutOfBoundsException等, 这些异常是不检查的异常,是在程序运行的时候可能会发生的, 所以程序可以捕捉, 也可以不捕捉. 这些错误一般是由程序的逻辑错误引起的, 程序应该从逻辑角度去尽量避免
2.非运行时异常是运行时异常以外的异常, 也是Exception及其子类, 这些异常从程序的角度来说是必须经过捕捉检查处理的, 否则不能通过编译. 如IOException、SQLException等

Error是程序无法处理了, 如OutOfMemoryError、OutOfMemoryError等等, 这些异常发生时, java虚拟机一般会终止线程

1.为什么要自定义异常封装?

Java语言的异常处理机制可以确保程序的健壮性,提高系统的开发效率,但是Java API提供的异常都是比较低级(这里的低级指的是“低级别的异常”),只有开发人员才能看的懂,才明白发生了什么问题。对于终端用户来说,这些异常基本上是天书,与业务无关,是纯计算机语言的描述
这就需要我们对异常进行封装了。

2.自定义异常封装有哪些优点?

2.1 提高系统的友好性

例如,打开一个文件,如果文件不存在,则会报FileNotFoundException异常,如果该方法的编写不做任何处理,直接上抛上层,则会降低系统的友好性,代码如下所示:

public static void doStuff()throws Exception{   InputStream is = new FileInputStream("无效文件.txt");   /*文件操作*/
}

此时doStuff方法的友好性极差:出现异常时(比如文件不存在),该方法直接把FileNotFoundException异常抛出到上层应用中(或者是终端用户),而上层应用(或用户)要么自己处理,要么接着抛出,最终的结果就是让用户对着“天书”式的文字发呆,用户不知道这是什么问题,只是系统告诉他”哦,我出错了,什么错误?你自己看着办吧“。
解决办法就是封装异常,可以把系统的阅读者分为两类:开发人员和用户。开发人员查找问题,需要打印出堆栈信息,而用户则需要了解具体的业务原因,比如文件太大,不能同时编写文件等,代码如下:

public static void doStuff2()throws MyBussinessException{   try{   InputStream is = new FileInputStream("无效文件.txt");   }catch(FileNotFoundException e){   //为了方便开发和维护人员而设置的异常信息   e.printStackTree();   //抛出业务异常   throw new MyBussinessException(e);   }
}

2.2 提高系统的可维护性

public void doStuff(){   try{   //do something   }catch(Exception e){   e.printStackTrace();   }
}

这是很多程序员容易犯的错误,抛出异常是吧?分类处理多麻烦,就写一个catch块来处理所有异常吧。而且还信誓旦旦的说”JVM会打印出栈中的错误信息“,虽然这没有错,但是该信息只有开发人员自己才看的懂,维护人员看见这段异常基本上无法处理,因为需要深入到代码逻辑中去分析问题。
正确的做法是对异常进行分类处理,并进行封装输出
,代码如下:

public void doStuff(){
try{   //do something   }catch(FileNotFoundException e){   log.info("文件夹未找到,使用默认配置文件....");   }catch(SecurityException 3){   log.info("无权访问,可能原因是....");   e.printStackTrace();   }
}

如此包装后,维护人员看到这样子的异常就有了初步的判断,或者检查配置,或者初始化环境,不需要直接到代码层级去分析了。

2.3 解决Java异常机制自身的缺陷

Java中的异常一次只能抛出一个,比如,doStuff方法有两个逻辑代码片段,如果在第一个逻辑片段中抛出异常,则第二个逻辑片段就不执行了,也就无法抛出第二个异常了。那么如何才能一次抛出两个异常呢?
其实,使用自行封装的异常可以解决问题,代码如下

class MyException extends Exception{   //容纳所有异常   private List<Throwable> causes = new ArrayList<Throwable>();   //构造函数,传递一个异常列表   public MyException(List<? extends Throwable> _causes){   cause.addAll(_causes);   }   //读取所有的异常   public List<Throwable> getException(){   return causes;   }
}

MyException异常只是一个异常容器,可以容纳多个异常,但它本身并不代表任何异常含义,它所解决的是一次抛出多个异常的问题,具体调用如下:

public static void doStuff()throws MyException{   List<Throwable> list = new ArrayList<Throwable>();   //第一个逻辑片段   try{   //Do something   }catch(Exception e){   list.add(e);   }   //第二个逻辑片段   try{   //Do something   }catch(Exception e){   list.add(e);   }   //检查是否有必要抛出异常   if(list.size() > 0){   throw new MyException(list);   }
}

这样一来,doStuff方法的调用者就可以一次获得多个异常,也能够为用户提供完整的例外情况说明。
那么在什么情况下,需要一个方法抛出多个异常呢?比如Web界面注册时,展示层依次把User对象传递给逻辑层,Register方法需要对各个Field进行校验并注册,例如,用户名不能重复,密码必须符合密码策略等,不要出现第一次提交系统提示”用户名重复“,在修改在提交后,系统提示“密码长度少6位”的情况,这种操作模式用户体验非常糟糕,最好的解决办法就是封装异常,建立异常容器,一次性地对User对象进行校验,然后返回所有异常。

3. 如何进行自定义异常封装?

3.1、添加一个枚举LuoErrorCode.java如下

package com.luo.errorcode;public enum LuoErrorCode {NULL_OBJ("LUO001","对象为空"),ERROR_ADD_USER("LUO002","添加用户失败"),UNKNOWN_ERROR("LUO999","系统繁忙,请稍后再试....");private String value;private String desc;private LuoErrorCode(String value, String desc) {this.setValue(value);this.setDesc(desc);}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}@Overridepublic String toString() {return "[" + this.value + "]" + this.desc;}
}

注意!!!这里我们重写了LuoErrorCode的toString方法,至于为什么要这样,后面会提到,客观请继续看。

3.2、创建一个异常类BusinessException.java,继承RuntimeException:

package com.luo.exception;public class BusinessException extends RuntimeException {private static final long serialVersionUID = 1L;public BusinessException(Object Obj) {super(Obj.toString());}}

这里的代码虽然短,但是有两点需要注意的!!!第一点是其继承了RuntimeException,因为一般我们的业务异常都是运行时异常。第二点,这里的构造方法调用父方法super(Obj.toString());,这就是重写了LuoErrorCode的toString方法的原因了,如果还不明白,看完后面的你就明白了。

3.3、测试类ExceptionTest.java:

package com.luo.test;import com.luo.errorcode.LuoErrorCode;
import com.luo.exception.BusinessException;public class ExceptionTest {public static void main(String args[]) {Object user = null;if(user == null){throw new BusinessException(LuoErrorCode.NULL_OBJ);}}
}

运行结果:

在我们实际项目里面,比如别人调用你接口,你可能需要先看他传过来的对象是不是空的,先判断如果传过来的对象为空给有友好的提示”[LUO001]对象为空”,不然后面的代码估计会出现空指针异常了。
一般公司都会分装一个基础框架,异常分装是其中一部分,当然他们对异常的分装肯定比我这个例子复杂多,因此本例仅供参考!
原创:
https://blog.csdn.net/qq_34309305/article/details/79202929
https://blog.csdn.net/u014754272/article/details/104765665
https://www.jianshu.com/p/a874e5d1bed1

Java自定义异常封装相关推荐

  1. java 自定义异常的回顾

    一.异常的分类: 1.编译时异常:编译时被检测的异常 (throw后,方法有能力处理就try-catch处理,没能力处理就必须throws).编译不通过,检查语法(其实就是throw和throws的配 ...

  2. java+自定义异常类+输入若干成绩 为负数时输出抛出异常_java+自定义异常类+输入若干成绩 为...

    java+自定义异常类+输入若干成绩 为 [2021-02-10 19:00:54]  简介: java中定义类的关键字是:"class".在Java中定义一个类,需要使用&quo ...

  3. 用枚举来处理java自定义异常

    用枚举来处理java自定义异常 参考文章: (1)用枚举来处理java自定义异常 (2)https://www.cnblogs.com/leskang/p/8119099.html 备忘一下.

  4. java自定义异常及异常的抛出

    java自定义异常及异常的抛出 参考文章: (1)java自定义异常及异常的抛出 (2)https://www.cnblogs.com/gemiaomiao/p/11900564.html 备忘一下.

  5. java的封装性_Java10-java语法基础(九)——java的封装性

    Java10-java语法基础(九)--java的封装性 一.Java的三大特性:封装.多态.继承 封装:通过类封装对象的数据成员和成员方法,保证只有可信的类或者对象能够访问这些方法和数据成员,对不可 ...

  6. java catch自定义异常_java异常类-java自定义异常-嗨客网

    Java异常类教程 我们在 我们可以看到,在 Exception 表示的是程序中出现了问题,可以直接使用 try - catch 来捕获处理.Error 一般值 Java常见异常 类名 描述 IOEx ...

  7. Java自定义异常、全局捕获异常、拦截器 实现动态控制登录超时

    Java自定义异常.全局捕获异常.拦截器 实现动态控制登录超时 参考文章: (1)Java自定义异常.全局捕获异常.拦截器 实现动态控制登录超时 (2)https://www.cnblogs.com/ ...

  8. 【知了堂学习笔记】java 自定义异常

    [知了堂学习笔记]java 自定义异常 参考文章: (1)[知了堂学习笔记]java 自定义异常 (2)https://www.cnblogs.com/pipixiao/p/7419902.html ...

  9. java 自定义异常实例分析_Java自定义异常类的实例详解

    Java自定义异常类的实例详解 为什么要自己编写异常类?假如jdk里面没有提供的异常,我们就要自己写.我们常用的类ArithmeticException,NullPointerException,Ne ...

最新文章

  1. c语言二级编程题答案免费下载,全国计算机等级考试二级C语言上机编程题参考答案...
  2. 关键词提取算法—TF/IDF算法
  3. linux平台下Tomcat的安装与优化
  4. 爬虫爬出来的数据不全_斥巨资学完Python数据分析后,给运营人总结7个小建议...
  5. 双向链表删除节点时间复杂度_「十分钟学算法」删除链表的倒数第N个节点
  6. React开发(262):react中活动时间回显用moment
  7. android.util.Base64 和 org.apache.commons.codec.binary.Base64
  8. PAP CHAP认证
  9. python监控错误语句_Sentry错误日志监控使用方法解析
  10. python程序化设计正则表达式语法_基于python的正则表达式学习笔记
  11. 大学计算机基础word操作2018,大学计算机基础试题及答案2017
  12. 联想电脑管家不显示开机时间_联想电脑怎么设置显示开机时间
  13. 达尔文服务器_达尔文与网络设计艺术
  14. windows ------ 证书导入(安装)
  15. 电影周周看——适合新手学习的微信小程序
  16. php后台视频教程,php实战开发电商后台视频教程 共6章
  17. 多个tab页如何共享websocket
  18. 微信web开发者工具-移动调试iphone端的调试
  19. android fuse 检测原理,fuse 原理总结
  20. 盘点那些年 半死不活的国产操作系统们

热门文章

  1. FVM in CFD 学习笔记_第7章_OpenFOAM和uFVM中的有限体积网格
  2. 怎么将excel中的一列数据变成一行数据,且数据之间用逗号隔开。
  3. Nuvoton NK-980IOT开发板 u-boot 编译
  4. RS232/RS422/RS485串口引脚连线
  5. 微信公众号验证token+关注回复+关键字回复+单图文回复
  6. [微信开发] 微信公众号被关注后如何回复多条消息?
  7. 推荐一款笔记本电脑_笔记本电脑破裂的那一天
  8. java十六进制字符串和中文(字符串)互转以及转换乱码问题总结
  9. Flunent-流体仿真理论和软件操作
  10. 2022 年 MathorCup 高校数学建模挑战赛——大数据竞赛(北京移动用户体验影响因素研究全套代码)