[疯狂Java]面向对象:不可变类

1. final只是保证被修饰的变量的值不可变!

    1) 注意!保证的是值不可变,什么是值?对于一个引用来说,就是指针咯,即指针的值不变,即其指向不变,但是我还是可以通过这个指针来调用可以改变该对象成员的方法啊!!

    2) 即final如果修饰引用变量,只能保证该引用的指向不变,但不能保证该引用指向的对象不变,其指向的对象还是可以改变的!!

    3) 例如:final Person p = new Person("Tom");  p.setName("Peter");是允许的!!


2. 不可变类:

    1) 不可变类是指创建该类的对象后,这些对象的数据成员都不能改变;

    2) 这种需求是普遍的,例如Java的8个包装器类型以及String类都是不可变类;

    3) 那该如何设计自己的不可变类呢?三原则:

         i. 数据成员都是private final的!这是显然的;

         ii. 只提供getter,不能提供setter!这也是显然的;

         iii. hashCode和equals应该根据数据成员计算得来,并且hashCode相等的情况下也要保证equals相等;

     4) 有了以上三原则就基本能保证设计的类是不可变的了;

!!什么叫做基本?难道这样还不能保证是不可变类吗?

!!诚然,如果数据成员都是Integer、String这些本身就是不可变类,那当然没有问题,但往往业务上你想包含的数据成员都是其它公司开发的类库中的类,而很多类本身设计时都是可变的,但你往往有得不到这些类库的源码,因此你无法通过改动源码的方式把这些类改成不可变类;

     5) 因此现在的问题是,如果你想把一个包含可变类对象的类设计成不可变类应该如何做呢?

          i. 其实思路很简单!无非就是从两个方面出发:

             a. 所有在类内部对该可变成员的访问一定要保证不能对其进行修改。这是显而易见的!根本不用说都应该能想到;

             b. 另外可能发生修改隐患的地方就是返回这个可变成员的地方了:如果一个方法返回的刚好就是这个可变成员,那么返回后在类的外部就完全有可能对该成员进行修改了(即返回数据成员也是一种暴露类的内部情况的一种情形);

          ii. 因此需要做文章的地方就在于b.了;

          iii. 其实应对策略也很简单,你只要创建一个该成员的副本并返回就行了,这样的话外界拿到的仅仅是该成员的副本,对副本修改不会影响到原本;

     6) 示例:

class Test {
	private final StringBuilder name; // 故意用StringBuilder,因为它是一个可变类
	public Test(StringBuilder name) {
		this.name = name;
	}
	public StringBuilder getName() {
		return new StringBuilder(name); // 返回一个临时创建的副本,外界对副本的改变不会影响原本
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值