`

安全的类构造器[摘自effective java]

阅读更多

原始的类的设计如下

import java.util.Date;

public final class SafeMain {
	
	private final Date start;
	
	private final Date end;
	
	private final int name;
	
	public SafeMain(Date start,Date end,int name){
		if (start.compareTo(end)>0) {
			throw new IllegalArgumentException();
		}
		this.start = start;
		this.end = end;
		this.name = name;
	}

	public Date getStart() {
		return start;
	}

	public Date getEnd() {
		return end;
	}

	public int getName() {
		return name;
	}

	@Override
	public String toString() {
		return "SafeMain [start=" + start + ", end=" + end + ", name=" + name
				+ "]";
	}
}

 但是可能存在如下的攻击

	public static void main(String[] args) {
		//TOCTOU 
		//1
		Date start = new Date();
		Date end = new Date();
		int name = 111;
		SafeMain safeMain = new SafeMain(start, end,name);
		end.setYear(78);
		name = 23456;
		System.out.println(safeMain.getEnd().getYear());
		System.out.println(safeMain.toString());
		
		//2
		safeMain.getEnd().setYear(888);
	}

 最开始的设计是end大于start才满足要求.而且这里的start和end都是不可变的(按照原始的累的设计的要求是这样的),这2中攻击都使类的设计失效.

修正之后的类

public final class SafeMain {
	
	private final Date start;
	
	private final Date end;
	
	private final int name;
	
	public SafeMain(Date start,Date end,int name){
		this.start = start;
		this.end = end;
		this.name = name;
		if (this.start.compareTo(this.end)>0) {
			throw new IllegalArgumentException();
		}
	}

	public Date getStart() {
		return new Date(start.getTime());
	}

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

	public int getName() {
		return name;
	}

	@Override
	public String toString() {
		return "SafeMain [start=" + start + ", end=" + end + ", name=" + name
				+ "]";
	}
}

 完美的避免了攻击

不止是在不可变的类的设计中这样保护性拷贝属性,某一些类的属性有一定的限制,在被后面的程序修改之后会产生不可预计的错误,也可以这样做.

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

Global site tag (gtag.js) - Google Analytics