异常总结
作者:互联网
异常
充分发挥异常的优点,可以提高程序的可读性、可靠性和可维护性。
1、 只针对异常的情况使用异常(异常适用于不正常的情形,)
不要在循环或者其他vm已经存在的机制中使用异常,例如:for循环中的每次数组访问都会检查是否越界异常,1、再加一次异常检验无疑是多余的;2、自加异常同时阻止住了jvm本来可能要执行的某些特定优化。3、增大了调试的复杂性
2、 对可恢复的情况使用受检异常,对编程错误使用运行时异常
Java提供了三种可抛出结构(throwable):checked exception、run-timeexception、error。
使用场景:
受检异常(Checked exception ):期望调用者适当恢复。
未受检异常(run-timeexception、error):如果程序抛出未受检异常,往往属于不可恢复状况;若没有捕获到,将会导致当前线程停止,同时出现适当的错误消息。
一般情况下,可恢复状况使用受检异常;程序错误使用运行时异常。特例,如资源枯竭可使用受检异常。
3、 避免不必要的使用受检异常
如果方法之抛出单个受检异常,应该考虑是否有别的途径避免受检异常,比如方法返回true或false来重构,只要是在合理的位置,这样的使用方式总是最方便灵活的。
4、 优先使用标准的异常
所有错误方法的调用都是非法参数或非法状态。
应该追求并通常也应该事先高度的代码重用,异常也不例外。
优:使你的api已与学习跟使用;可读性会更好,不会出现不熟悉的异常;异常类越少,内存印迹越小,装在这些类的时间开销也越少(作者说这也是最不重要的,我觉得原作者是想表达:易于维护>开销)
a):IllegalArgumentException,经常被重用。调用的传参不合适会抛出该异常,例如数值传递。
b):IllegalStateException。因接收对象状态异常调用,抛出该异常。如:初始化之前调用。
c):ConcurrentModificationException。对象被设计为专用于单线程或配合外部同步使用,如果被并发修改,抛出该异常。
d):UnsupportedOperationException。对象不支持调用的操作,抛出该异常。如:只支持追加操作的List实现,若删除元素,会抛出该异常。
异常 使用场合
IllegalArgumentException 非null的参数值不正确
IllegalStateException 对方法的调用,对象状态不合适
NullPointerException 禁止使用null却使用了null
IndexOutOfBoundsException 下标参数越界
ConcurrentModificationException 禁止并发修改,却用来并发修改
UnsupportedOperationException 不支持请求方法
作者最后说:选择重用那个异常并不总是那么精确。
5、 抛出与抽象相对应的异常
异常链:高层异常应该捕获低层异常,同时抛出按照高层抽象进行解释的异常,这种方法称做“异常转译”。
AbstractSequentialList
(注:如果不能阻止或处理低层的异常,通常做异常转译。一种情况除外:低层到高层的异常均适用)
6、 每个方法抛出的异常都要有文档
大家都知道依照Javadoc的格式进行注释文档,异常也需要这么做。
关键字 @throws。
如果有多个异常,不要声明一个throw Exception,更不要声明一个throws Throwable。这种方式首先没有提供任何的指导信息,其次还妨碍了该方法的使用(掩盖了有可能的其他异常)。
7、 在细节消息中包含能捕获失败的信息
打印异常的堆栈轨迹:异常类名+细节信息(明确的文件和行数以及所有调用的其他方法的文件和行数)。
作者推荐:在异常的构造器而不是字符串细节消息中引入这些信息(java没有引入,但是非常值得提倡)。
好处就是只要放到消息描述中就可以自动产生细节消息,而不是写定的异常字符串信息。
优先使用:
异常构造器 > 异常字符串
异常的细节信息:对该异常有贡献的 参数、域值。
8、 努力使失败保持原子性
失败的方法调用应使对象保持在被调用之前的状态。
实现方法:
a):设计一个不可变对象。
b):执行之前检查参数有效性,使修改前抛出适当异常。
c):调整计算顺序,使可能失败的计算处在对象被修改前发生。
d):编写恢复代码。主要用于永久性数据结构。
并不是都能实现失败原子性。不可恢复的错误,不用非得保持失败的原子性。
9、 不要忽略异常
比如tary-catch捕获后并不处理。
关闭FileInputStream的时候可以(最好也捕获)异常。
标签:总结,调用,受检,抛出,方法,使用,异常 来源: https://blog.51cto.com/u_8056676/2829090