(39):必要时进行保护性拷贝

来源:互联网 发布:北京淘宝的地方在哪里 编辑:程序博客网 时间:2024/05/20 07:34

看下面这个例子

public final class   Period{         private   final   Date   startTime;         private   finale  Date   endTime;         public   Period(Date  startTime , Date  endTime)        {               if(startTime.compareTo(endTime) > 0)               { throw   new  IllegalArgumentException(“startTime  after  endTime !”);  }                this.startTime = startTime;                this.endTime  = endTime;        }        pubilc   Date   start()        {  return   this.startTime ; }        public   Date  end()        { return  this.endTime  ; }}
上面这段程序乍一看是不可变的,但事实上它有许多漏洞。
Date  startTime   =  new Date();Date  endTime   = new  Date();Period  per =  new  Period(startTime ,  endTime );endTime.setYear(78);
我们通过改变Date类就可以改变Period,这时候我们就应该对构造器进行改造

public   Period(Date   startTime , Date  endTime ){      this.startTime  =  new Date (startTime.getTime());      this.endTime   =  new  Date(endTime.getTime());     if(this.startTime.compareTo(this.endTime)  >  0)    {           throw   new    IllegalArgumentException(“startTime  after   endTime !”);    }}
但只是改变构造器也是不够的,start()、end()返回的Date也是可变的。如

per.start().setYear(78);
改造一下:

public  Date   start(){      return   new  Date(startTime.getTime());}public  Date  end(){      return  new   Date(endTime.getTime());}
这样就真正实现了不可变。
保护性拷贝不仅仅只是针对不可变类。如果我们不能容忍对象进入数据结构后可以变化,我们也应该考虑保护性拷贝。

所以说我们应该尽量使用不可变的对象作为对象内部组件,这样就不必考虑保护性拷贝的问题了。

如果类具有从客户端得到或者返回客户端的可变组件,类就必须保护性地拷贝这些组件,如果拷贝成本受到限制,并且类信任调用者不会修改内部组件,不进行保护性拷贝也是可以的,类的文档必须清楚说明这一点。


0 0