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

import java.util.Date;public final class Period {private final Date start;private final Date end;public Period(Date start,Date end) {if(start.compareTo(end) > 0){throw new IllegalArgumentException(start + " after " + end);}this.start = start;this.end = end;}public Date start(){return start;}public Date end(){return end;}//remainder omitted
}

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

     Date start = new Date();Date end = new Date();Period period = new Period(start, end);end.setYear(78);System.out.println(period.end());

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

 public Period(Date start,Date end) {this.start = new Date(start.getTime());this.end = new Date(end.getTime());if(this.start.compareTo(this.end) > 0){throw new IllegalArgumentException(this.start + " after " + this.end);}}      

保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是原始对象。

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

通过改变Period:

     Date start = new Date();Date end = new Date();Period period = new Period(start, end);period.end().setYear(98);System.out.println(period.end());

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

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

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

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

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

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

第39条:必要时进行保护性拷贝相关推荐

  1. Effective Java之必要时进行保护性拷贝(三十九)

    我们来看一个不可变对象的攻守问题: public class Period{private final Date startTime;private finale Date endTime;publi ...

  2. 必要时进行保护性拷贝

    假设类的客户端会尽其所能来破坏这个类的约束条件,因此你必须保护性的设计程序. demo: 1 import java.util.Date; 2 3 public final class Period ...

  3. 39条常见的Linux系统简单面试题

    39条常见的Linux系统简单面试题 本文主要分享39条常见的Linux系统简单面试题,其中包括如何看当前Linux系统有几颗物理CPU和每颗CPU的核数.如何实时查看网卡流量为多少等等,希望对你有所 ...

  4. 保护性拷贝(defensive copy)

    何为保护性拷贝?看一个例子: public class Person {private String name;private Date birth;public Person(String name ...

  5. 我的世界服务器无限开号,我的世界开挂指令大全表一览!39条命令无限可能性

    游戏开挂游戏中很多玩家都是非常认为可耻的,但是在我的世界手游中来说,却是被允许的,玩家不管使不适用,却要掌握这些我的世界开挂指令大全,不然当你进入作弊模式世界,那么可能你无法生存,当然如果在这里你掌握 ...

  6. 用39条Python语句完成“数字华容道”游戏

    原以为用Python编写"数字华容道"游戏可能需要很多代码,完成后发现只用了39条语句,可见Python的强大.编程的思路如下,使用9个tkinter库的Button按钮,按3行3 ...

  7. 7.39 必要时使用保护性复制(defensive copy)

    以下Period类用于表示两个日期之间的间隔: import java.util.Date;public class Period {private Date start;private Date e ...

  8. 39条常见的Linux运维面试题,有备无患!

    1.如何看当前Linux系统有几颗物理CPU和每颗CPU的核数? 答:[root@centos6 ~ 10:55 #35]# cat /proc/cpuinfo|grep -c 'physical i ...

  9. 读effection java

    1.考虑用静态工厂方法代替构造器 public static Boolean valueOf(boolean b){ return b?Boolean.TRUE:Boolean.FALSE; } 静态 ...

最新文章

  1. Mybaits整合Spring自动扫描 接口,Mybaits配置文件.xml文件和Dao实体类
  2. IOS开发基础知识--碎片34
  3. iOS 配置pch文件
  4. 扒几个 3D 模型备用
  5. 牛客每日一题3.31 城市网络 树上倍增
  6. DP问题之 捞鱼问题
  7. x86服务器当虚拟化的存储,龙存科技-软件定义数据中心产品提供商
  8. 英雄无敌6服务器在哪个文件夹,Win7系统无法运行英雄无敌6的两种原因和解决方法...
  9. 基于id3算法根据房价数据进行画图预测python
  10. Jquery.Validation表单验证
  11. Python实践周 A卷 试题(不印刷)
  12. python 怎么样才有output_[学]Python用户手册笔记_4_Input and Output
  13. 读《人工智能,李开复王咏刚》
  14. SCI论文配色-matplotlib分类柱状图绘制
  15. 视频渲染靠cpu还是显卡 视频渲染的作用是什么
  16. outlook登录QQ邮箱
  17. 银汇通无线pos机的优势与区别
  18. 事情往往不是想的那么糟
  19. 网络流媒体--RTP和RTCP协议
  20. 工勤人员计算机考试内容,事业单位工勤人员计算机文字录入员考试大纲初级.doc...

热门文章

  1. 研发管理中存在的问题
  2. 位置特异性得分矩阵_线性代数-2.矩阵
  3. All in 凉凉!德州赔率怎么算?我用Python来搞定!
  4. 哈密顿回路C/c++
  5. 游戏开发unity资源管理系列:unity不支持长路径;DirectoryNotFoundException: Could not find a part of the path ““
  6. Server List for eDonkey and eMule
  7. 每日一题---20200429---五个水手在岛上发现一堆椰子,先由第1个水手把椰子分为等量的5堆,还剩下1个给了猴子,自己藏起1堆。迭代法
  8. Linux初始化Root密码命令
  9. DeFi借贷VS传统金融“无风险”利率产品
  10. 前端精美的 后台模板