zoukankan      html  css  js  c++  java
  • 必要时进行保护性拷贝

    假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性的设计程序。
    demo:

     1 import java.util.Date;
     2 
     3 public final class Period {
     4     private final Date start;
     5     private final Date end;
     6     public Period(Date start,Date end) {
     7         if(start.compareTo(end) > 0){
     8             throw new IllegalArgumentException(start + " after " + end);
     9         }
    10         this.start = start;
    11         this.end = end;
    12     }
    13     
    14     public Date start(){
    15         return start;
    16     }
    17     
    18     public Date end(){
    19         return end;
    20     }
    21     //remainder omitted
    22 }

    这个类看上去没有什么问题,时间是不可改变的。然而Date类本身是可变的。

    1         Date start = new Date();
    2         Date end = new Date();
    3         Period period = new Period(start, end);
    4         end.setYear(78);
    5         System.out.println(period.end());

     

    为了保护Period实例的内部信息避免受到修改,导致问题,对于构造器的每个可变参数进行保护性拷贝(defensive copy)是必要的:

     
    1     public Period(Date start,Date end) {
    2         this.start = new Date(start.getTime());
    3         this.end = new Date(end.getTime());
    4         if(this.start.compareTo(this.end) > 0){
    5             throw new IllegalArgumentException(this.start + " after " + this.end);
    6         }
    7     }        
    保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是原始对象。



    对于参数类型可以被不可信任方子类化的参数,请不要使用clone方法进行保护性拷贝。


    通过改变Period:

    1         Date start = new Date();
    2         Date end = new Date();
    3         Period period = new Period(start, end);
    4         period.end().setYear(98);
    5         System.out.println(period.end());

     

    为了防止二次攻击,可以让end()返回拷贝对象。

    1     public Date end(){
    2         return new Date(end.getTime());
    3     }

    但是这样让人写起来很浮躁,所以还是要有一个必要性的把握。



    参数的保护性拷贝不仅仅针对不可变类。每当编写编写方法和构造器时,如果他要允许客户提供的对象进入到内部数据结构中,则有必要考虑一下,客户提供的对象是否有可能是可变的,我是否能够容忍这种可变性。特别是你用到list、map之类连接元素时。


    在内部组件返回给客户端的时候,也要考虑是否可以返回一个指向内部引用的数据。或者,不使用拷贝,你也可以返回一个不可变对象。如:Colletions.unmodifiableList(List<? extends T> list)


    如果类具有从客户端得到或者返回到客户端的可变组件,类就必须保护性的拷贝这些组件。如果拷贝的成本受到限制,并且类信任他的客户端不会进行修改,或者恰当的修改,那么就需要在文档中指明客户端调用者的责任(不的修改或者如何有效修改)。
    特别是当你的可变组件的生命周期很长,或者会多层传递时,隐藏的问题往往暴漏出来就很可怕。

    进行保护性拷贝的设计原则就是,客户端使用类会破坏你设计类的原则,没有达到你程序需要的效果

    转载:http://blog.csdn.net/partner4java/article/details/7592950

     

  • 相关阅读:
    uip UDPclient模式通信移植,p本地ort可以是无规
    正则表达式摘要
    Regular expression
    正则-合乎规则
    通配符-通配
    正则表达式总结
    判断大盘筑顶的方法
    筑顶和下跌规律
    股票的筑顶危险信号
    股票筑顶的基本特征
  • 原文地址:https://www.cnblogs.com/huzi007/p/5424375.html
Copyright © 2011-2022 走看看