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