如何保证Java对象内部属性的不可变状态

很多人看到上面的提问,立刻就会想到 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对象返回出去,提供给客户端代码使用,这样无论客户端代码如何操作,都不会影响到原来的属性状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值