2015070505 - EffactiveJava笔记 - 第64条 努力保持失败原子性

   20150705 星期日 北京

   当对象抛出异常后,通常期望这个对象仍然保持在一种定义良好的可用状态,即使异常发生在执行某个操作的过程中间.这对于检查时异常尤为重要.因为调用者期望能从异常中进行恢复.

   一般而言,失败的方法调用应该使对象保持在被调用之前的状态.具有这种属性的方法被称为具有是失败原子性.

   如何实现失败原子性呢?

   第一种最简单的方法设计不可变对象,如果对象不必变,那么失败原则性是必然.如果一个操作失败,它可能会组织创建新的对象,但永远不会使已有的对象保持在不一致的状态中,因为每个对象被创建后就处于一致的状态,以后再也不会改变.(实在没看懂)

   第二种对于可变对象上执行操作的方法,获得失败原子性最常见的方法是,在执行操作之前检查参数有效性.使得对象状态被改变之前,先抛出适当异常.

   类似获取失败原子性的方法,调整计算过程顺序,使得任何可能导致失败的计算部分都在对象被改变之前发生.如果对参数检查只有执行部分计算后才进行,实际上就是上面方法的拓展而已.

   例如,考虑TreeMap情景,它的元素按照某种特定顺序排列,添加元素时,该元素的类型必须可以利用TreeMap的排序规则和其他元素比较.如果企图添加不正确的元素,在tree以任何方式被修改之前,自然会导致ClassCastException异常.

   第三种不太常用的操作方法,编写一段恢复代码,由它来拦截操作过程中发生的失败,以及使对象回滚到操作开始之前的状态.这种方法主要用于永久性数据结构(存在磁盘中).

   第四种方法是,在对象的一份临时拷贝上执行操作,当操作完成在用临时性拷贝的结果代替对象的内容.

   例如.Collections.sort在执行排序之前,需要把输入列表转到一个数组中,以便降低排序内循环中访问元素的开销.虽然是出于性能考虑,但是及时排序失败,能保证输入列表保持原样.

 

   虽然希望保持对象的失败原子性,但是并不是总能实现.比如两个线程企图在没有恰当的同步机制下并发修改某个对象,那么这个对象就可能被保留在不一致状态中.捕获ConcurrentmoodificationException异常后对象就是不可能用的.而当方法抛出Error时,不可恢复的,对象无法保持失败原子性的.

   如果实现失败原子性,那么会明显增加开销或者复杂性,那么需要衡量利弊再决定如何处理.

 

   一般而言,作为方法规范的一部分,产生的任何异常都应该让对象保持在该方法调用之前的状态.如果违反这条准则,API文档应该清楚指明对象会处于什么状态.遗憾的是,大部分API没有做到.

   {你如何使用上面的知识呢?

   1.发生异常,对象要保持在方法调用之前的状态.

   2.检查参数的有效性可以实现

   3.使用对象的拷贝可以实现

   4.如果增加性能和复杂性,衡量利弊再决定

   5.在方法的文档中,说明如果发生异常,对象处于什么状态,需要明显地指出来}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值