Java 不可变类


本文整理自《Effective Java》一书。


不可变类,并在对象的整个生命周期(lifetime)内保持不变。Java平台类库中包含许多不可变的类,其中有String、基本类型的包装类、BigInteger、BigDecimal

为了使类成为不可变,要遵循下面五条规则:

1.不要提供任务会修改对象状态的方法。

2.保证类不会被扩展。常见做法final Class、 private constructor并添加公有的静态工厂(static factory)来代替公有的构造器,如 public static Complex valueOf(){ return new Complex();}。

3.使所有的域都是final的。final

4.使所有的域都成为私有的。private

5.确保对于任何可变组件的互斥访问。采用函数的(functional)做法,防止this引用逸出,如String中的做法:

public static String copyValueOf(char data[]) {
        return new String(data);
}

不可变对象本质上是线程安全的,它们不要求同步。当多个线程并发访问这样的对象时,它们不会遭到破坏,所以,不可变对象可以被自由的共享。不可变类应该充分利用这种优势,鼓励客户端尽可能地重用现有的实例,对于频繁用到的值,为它们提供公有的static final 常量,如 Integer 提供的 public static final intMIN_VALUE =-231


不可变类的真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。创建这种对象的代价可能很高,特别是对于大型对象的情形。所以,最好的办法是提供一个公有的可变配套类。在Java平台类库中,这种方法的主要例子是String类,以及它的可变配套类StringBuilder(和基本上已经废弃的StringBuffer)


当BigInteger和BigDecimal刚被编写出来的时候,对于“不可变的类必须为final的”还没有得到广泛地理解,所以它们的所有方法都可能被覆盖,遗憾的是,为了保持向后兼容,这个问题一直无法得以修正。

public class BigDecimal
extends Number
implements Comparable<BigDecimal>

如果你在编写一个类,它的安全性依赖于BigInteger或者BigDecimal参数的不可变性,就必须进行检查,以确定这个参数是否为“真正的”BigInteger或者BigDecimal,而不是不可信任子类的实例。如果是后者的话,就必须在假设它可能是可变的前提下对它进行保护性拷贝:

public static BigInteger safeInstance(BigInteger val){
	if(val.getClass()!= BigInteger.class){
		return new BigInteger(val.toByteArray());
	}
	return val;
}

实际中,上述规则规定不可变类的所有域都必须是final的。这个要求为了提高性能可以有所放松,只要没有一个方法能够对对象的状态产生外部可见的改变。如String类的

/** Cache the hash code for the string */private int hash; 采用延迟初始化来缓存一些开销昂贵的计算结果到这些域中

除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。关于final域:"When final is used withobject references rather than primitives, the meaning can be confusing. With aprimitive, final makes the value a constant, but with an object reference,final makes the reference a constant. Once the reference is initialized to anobject, it can nerver be changed to point to another object. However, theobject itself can be modified." FromThinking in Javafinal修饰域时,只保证引用的不可变,而不保证引用指向的对象不可变,除非这个对象本身是不可变。请一定确保公有类的公有static final域所引用的对象都是不可变的



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值