java编程之--当类的访问器邂逅可变对象成员时

首先声明,本文所阐述的问题,源于《Java核心技术:卷1基础知识》P108,文中所用例子和步骤均为作者本人亲自实践。

在编写Java类的时候,其中一个重要步骤,就是为数据域编写访问器。见下例,是一个交易类Deal的源代码和测试代码:

java.util.*;
class Deal {
    //构造器。
    public Deal(int year, int month, int day, String info) {
        //使用GregorianCalendar类来生成Date对象。
        GregorianCalendar c = new GregorianCalendar(year, month-1, day);
        this.date = c.getTime();
        this.info = info;
    }
    
    //访问器:交易日期。
    public Date getDate() {
        return date;
    }

    //访问器:交易信息。
    public String getInfo() {
        return info;
    }

    private Date date; //交易日期。
    private String info; //交易信息。
}

public class DealTest {
    public static void main(String[] args) {
       Deal d = new Deal(2014, 7, 17, "This is a TRAP!");
       
       System.out.println("deal date:"+ d.getDate());
       Date hunter = d.getDate(); //
       long someTimeInMillSecs = 10 * 24 * 60 * 60 * 1000; //10天的毫秒数.
       hunter.setTime(hunter.getTime() - someTimeInMillSecs);
       
       //啊哦!结果或许会出乎意料~
       System.out.println("Your are hunted:"+ d.getDate());
    }
}
编译运行,得到如下结果:

deal date:Thu Jul 17 00:00:00 CST 2014
Your are hunted:Mon Jul 07 00:00:00 CST 2014

Deal类中,并没有类似于setXXX()的修改器方法。可以说,它是只读的。

然而……从上述结果可以看出,我们通过一个hunter的对象,竟然修改了只读对象的日期!时间整整减少了10天!

为什么?原理很简单。请看下图:

因为Date是引用类型,Deal的访问器方法getDate()在return的时候,直接将引用返回给了hunter(此时它俩指向了堆中同一块区域),这样在hunter被修改的时候,Deal对象自然也被修改了。这样严重破坏了OOP的封装性。


   有没有什么解决的办法呢?有,最简单的就是:克隆一个给hunter不就行了吗?那样无论hunter怎么修改,它也动不了我们私有的数据了。
解决办法如下,将getDate()改写:

    public Date getDate() {
        return (Date)date.clone();
    }
这样问题应该就得到解决了。但是需要注意,被克隆的对象需要实现clonable接口。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值