您正在将每个员工的雇用日期更改为
新的日期对象,
所以这两个值是独立的是有意义的。
问题是,在调用复制构造函数之后,它们都共享
同一日期实例,
是可变的
setTime method
)如果通过调用其设置时间方法更改日期对象本身(而不是雇员属性),则可以看到以下效果:
Employee employee1 = new Employee();
employee1.setId(1);
employee1.setName("John");
employee1.setHireDate(new GregorianCalendar(2018, Calendar.DECEMBER, 19).getTime());
Employee employee2 = new Employee(employee1);
// Change the state of the Date object shared by both instances.
employee2.getHireDate().setTime(
new GregorianCalendar(2018, Calendar.JANUARY, 19).getTimeInMillis());
System.out.println("employee1.getHireDate()=" + employee1.getHireDate());
System.out.println("employee2.getHireDate()=" + employee2.getHireDate());
解决方案是对日期执行防御性复制:
public Employee(Employee e) {
this.id = e.id;
this.name = e.name;
this.hireDate = (e.hireDate != null ? (Date) e.hireDate.clone() : null);
}
另外,getter和setter方法应该做同样的事情:
public Date getHireDate() {
return hireDate != null ? (Date) hireDate.clone() : null);
}
public void setHireDate(Date newDate) {
this.hireDate = (newDate != null ? (Date) newDate.clone() : null);
}
这样,除非调用sethiredate方法(或者使用反射,但这是一个单独的问题),否则不能更改雇用日期。employee类可以完全控制自己的数据。