1,防御性编程。必要时应当考虑采取保护性拷贝的手段来保护内部的私有数据,先来看下面这个例子:

  1. pubic final class Period  
  2. {  
  3.     private final Date start;  
  4.     private final Date end;  
  5.       
  6.     public Period(Date start, Date end)  
  7.     {  
  8.         if (start.compareTo(end) > 0)  
  9.             throw new IllegalArgumentException(start + "after " + end);  
  10.         this.start = start;  
  11.         this.end = end;  
  12.     }  
  13.       
  14.     public Date getStart()  
  15.     {  
  16.         return start;  
  17.     }  
  18.     public Date getEnd()  
  19.     {  
  20.         return end;  
  21.     }  

这个类存在两个不安全的地方,首先来看第一个***代码

  1. Date start = new Date();  
  2. Date end = new Date();  
  3. Period p = new Period(start, end);  
  4. end.setYear(78);//改变p的内部数据!  

这是因为外部和内部引用了同样的数据,为了解决这个问题,应当修改Period的构造函数:

  1. public Period(Date start, Date end)  
  2. {  
  3.     this.start = new Date(start.getTime());  
  4.     this.end = new Date(end.getTime());  
  5.     if (start.compareTo(end) > 0)  
  6.         throw new IllegalArgumentException(start + "after " + end);  

这样内部的私有数据就与外部对象指向不同,则不会被外部改变

再来看第二个***代码:

  1. Date start = new Date();  
  2. Date end = new Date();  
  3. Period p = new Period(start, end);  
  4. p.getEnd().setYear(78);//改变p的内部数据!  

这很显然是由于公有方法暴露了内部私有数据,我们可以只返回内部私有数据的只读版本(即其一份拷贝)

  1. public Date getStart()  
  2. {  
  3.     return (Date)start.clone();  
  4. }  
  5. public Date getEnd()  
  6. {  
  7.     return (Date)end.clone();  

2,读到上面这个例子,我想起来了下面这样的代码片段

  1. public class Suit  
  2. {  
  3.     private final String name;  
  4.     private static int nextOrdinal = 0;  
  5.     private final int ordinal = nextOrdinal++;  
  6.       
  7.     private Suit(String name)  
  8.     {  
  9.         this.name = name;  
  10.     }  
  11.     public String toString()  
  12.     {  
  13.         return name;  
  14.     }  
  15.     public int compareTo(Object o)  
  16.     {  
  17.         return o  
  18.     }  
  19.     public static final Suit CLUBS = new Suit("Clubs");  
  20.     public static final Suit DIAMONDS = new Suit("diamonds");  
  21.     public static final Suit HEARTS = new Suit("hearts");  
  22.     public static final Suit SPADES = new Suit("spades");  
  23.       
  24.     private static final Suit[] PRIVATE_VALUES = {CLUBS,DIAMONDS,HEARTS,SPADES};  
  25.     public static final List VALUES = Collections.unmodifiedList(Arrays.asList(PRIVATE_VALUES));  
  26.       
  27.