7.39 必要时使用保护性复制(defensive copy)
生活随笔
收集整理的這篇文章主要介紹了
7.39 必要时使用保护性复制(defensive copy)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
以下Period類用于表示兩個日期之間的間隔:
?
import java.util.Date;public class Period {private Date start;private 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 boolean isValid(){return start.compareTo(end)<=0;}public Date getStart() {return start;}public Date getEnd() {return end;} }?
?
以下測試將失敗:
@Testpublic void testPeriod(){Date start=new Date();Date end=new Date();Period period=new Period(start, end);Assert.assertTrue(period.isValid());end.setYear(1);//修改了傳給Period的參數值Assert.assertTrue(period.isValid());period.getEnd().setYear(1);修改了Period返回的屬性值Assert.assertTrue(period.isValid());}?
?
如果要求Period的屬性start、end對外部是不可變的(即只有Period內部可以修改此屬性值,外部修改不會對屬性值有任何影響),那么需要對傳入的可變參數值和返回的屬性值(即start,end)進行保護性復制,修改后的Period如下:
?
public class Period {private Date start;private Date end;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("start after end");}public boolean isValid(){return start.compareTo(end)<=0;}public Date getStart() {//返回復制的對象return new Date(start.getTime());}public Date getEnd() {//返回復制的對象return new Date(end.getTime());} }?
?
另一種修改方式如下:
?
public class Period {//使用不可變的數據類型private long start;private long end;public Period(Date start,Date end){this.start=start.getTime();this.end=end.getTime();if(this.start>this.end)throw new IllegalArgumentException("start after end");}public boolean isValid(){return start<=end;}public Date getStart() {return new Date(start);}public Date getEnd() {return new Date(end);} }?
?
如果不希望外部修改引起類的屬性的變化,但是屬性的數據類型又是Date,Array,Collection,Map等可變類型,那么應使用保護性復制,使用原則如下:
1.在校驗輸入參數前進行保護性復制
2.如果屬性類型是可變的,在返回給調用者前應進行保護性復制
3.不要使用clone()進行保護性復制,clone()可能返回子類對象,可能導致惡意攻擊
?
保護性復制和不可變類一樣都可能引起性能問題,如果不能使用保護性復制,同時又希望外部修改不引起屬性變化,那么應在注釋里詳細說明,告訴調用者不要進行可能引起屬性值改變的修改。
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的7.39 必要时使用保护性复制(defensive copy)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mac vscode 配置php跳转
- 下一篇: (简单介绍)PageRank算法