目录 start
目录 end
|2018-05-26| 码云 | CSDN | OSChina
相关博客:Java异常浅谈
下面的部分文字内容来源于 JPM的GitChat 群里的交流
Java将所有非正常情况分为两种 异常(Exception)和错误(Error) 它们都继承Throwable父类。
Err错误,一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常应用程序无法处理这些错误;
因此应用程序不应该使用catch块来捕获Error对象,在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及任何子类。
所以异常处理更多的是指Exception类,而经常处理的一般是RunTimeException 而Exception又分为2种:校验异常 和 运行时异常
为了避免我们遗漏掉一些可能会出现异常的代码, 所以建议使用大块的try, 因为检查型异常是容易发现的, 但是运行时异常却往往不能在编码的第一时间发现
检验异常在开发中如果不进行处理(捕获处理或声明抛出)编译器就会报错不让通过的, 如果平时没有注意异常的系统性学习,
开发就会有这样一种现象: 程序中通篇只有校验异常. 一般这种校验异常默认的处理方式(使用IDE)是颗粒度小的.
但是程序运行出问题的大多是运行时异常, 空指针, 数组越界, 类型不匹配, 除数为0 等等.
使用大try就不会遗漏运行时异常,但是不能仅仅依靠他, 运行时异常还是尽量使用好的编程习惯来规避的.
当然也是可以在大try中使用小try进行开发这样就能对异常进行具体的捕获和处理以及响应
按下葫芦浮起瓢, 关于异常, 可以从另一个角度: 性能方面的维度去考虑:
异常机制的设计初衷是用于不正常的情形, JVM很少对其生成的字节码进行优化, 把尽可能多的代码放在try块中就会阻止了JVM实行原本可以执行的某些特定优化
具体业务具体分析, 如果要求循环一出问题后续的循环还是要继续执行, 那么就把try写到for中;
如果要求后续的循环不执行就用try包住for
另外: 使用多线程实现的定时任务在循环处理数据时出现异常必须要及时处理, 否则执行时就会退出
一般来说, 异常都是层层上抛, 中央处理 针对 Service Dao Controller 这种结构的设计, 在Service层进行统一异常处理
除非这个异常是无关大局的, 就是局部发生对其他模块和代码没有影响, 那么就可以就地捕获不需要上抛
不建议使用判断语句进行异常的处理, 这样的维护很费劲, 可读性也不好
大的try块中 一些需要特别说明的就是 特别处理的就要看情况抛出了, 一般进行封装后, 抛出自定义异常, 上层接收后, 进行二次处理和转化,
直到最外层的调用处, 由最外层调用者决定最终如何处理 只要在使用对象前进行对象的非空判断, 基本就能杜绝空指针异常,
方法一,nginx上设置拦截,配置对应的跳转页面。 方法二,添加监听器捕获输出异常,然后按自己需要组织返回Json
异常一定要和日志结合使用, 日志记录的简约优雅, 维护才越轻松, 日志的存在就是为了解决问题的方便和有迹可循,
所以要记录的任何信息都是为了解决问题, 无关信息就没有必要放进来了
目前个人用到的就是所在类 方法 行数 时间 报错信息, 根据业务需要还可以加上用户id, 订单id之类的
虽然Java提供了大量的异常类, 但是这些异常类还是难以满足业务的需求, 这个需求可能是用户, 客服, 我们自身
通常自定义异常只要继承Exception 重写相关构造器即可.
一般来说自定义异常具有以下类型: 业务异常, 用户异常, 系统异常, 接口异常, 网络异常, 参数异常等等.
根据项目需要, 可以将异常细分, 比如写一个订单保存, 那么针对订单保存的业务可以在不同的代码逻辑里提示不同的异常信息, 接口级异常也是如此
目的是为了将Exception进行封装, 形成易于理解的异常信息.
自定义异常的设计原则
正规项目中都会有接口文档, 也会有规范注释, 在项目中也会有一些静态常量
假设定义一个错误码 00X1 表示空指针, 这个错误码不是给客户或者使用者看的, 而且定义要有规律不能让其他人猜到, 方便查询和管理
规划的越详细, 就会有更为便利的维护方式