很多人看到上面的提问,立刻就会想到 final 关键字。但是却不完全正确。
看如下代码
private final int a;
private final Date date;
示例代码中分别声明了整型的属性a,Date型的属性date,final关键只能确保基本数据类型的值不会变,但是对于Date这样的,非基本数据类型,就需要注意了。
注意
Date这样的非基本数据类型,在内存分配时是占用两块内存的,首先date只是一个引用,其次这个引用指向一块存储数据的内存。
final关键字只能保证date的引用不会变,但若是客户端代码获得date引用,像下面这样调用方法,则数据状态被破坏了,
date.setDate(20);
如何防止属性状态被破坏
请看如下代码示例
public class DateTest {
private final Date date;
public DateTest (Date date){
this.date = new Date (date.getTime());
}
public Date getDate (){
return new Date (date.getTime());
}
}
上面的这段代码,粗略看,觉得很多余,在此,陈述一下我这样写的理由。
解释
我有一个DateTest类,且每次生成对象时,给它一个确定的日期,并且以后这个对象的状态都不能改变,那么我该怎么做,没错,就如同前面的代码示例。
1、在调用构造器new DateTest(date)时,从date的状态中获取它的值,生成一个新的date对象,并且将引用赋给本对象的date属性,而不是直接赋值引用,这样,当我用date属性操作时,不会因为误操作改变另一个对象的date状态;
2、当我调用getDate()方法时,获得了date属性的引用,但是我们的初衷是不改变date状态,若是直接返回本对象的date(return this.date),客户端使用date.setTime()时,经由这个引用,还是会操作本对象的属性,所以我使用的是return new Date(date.getTime()),通过内部状态新生成一个Date对象返回出去,提供给客户端代码使用,这样无论客户端代码如何操作,都不会影响到原来的属性状态。