• 必要时进行保护性拷贝


    假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性的设计程序。
    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

     

  • 相关阅读:
    IntelliJ IDEA 14.03 java 中文文本处理中的编码格式设置
    应聘感悟
    STL string分析
    CUDA SDK VolumeRender 分析 (1)
    BSP
    CUDA SDK VolumeRender 分析 (3)
    CUDA SDK VolumeRender 分析 (2)
    Windows软件发布时遇到的一些问题
    Ten Commandments of Egoless Programming (转载)
    复习下光照知识
  • 原文地址:https://www.cnblogs.com/huzi007/p/5424375.html
Copyright © 2020-2023  润新知