【Effective Java】使可变性最小化

本文深入探讨了不可变对象的概念,详细介绍了如何创建不可变类,包括五个关键规则。示例展示了不可变复数类的实现,其算术运算返回新的对象。不可变对象的主要优点包括简单性、线程安全和信息共享,而主要缺点是可能增加对象创建的开销。建议优先使用不可变类,并谨慎处理可变性。
摘要由CSDN通过智能技术生成

基础概念

不可变类是指其实例不能被修改的类,每个实例中包含的信息都应该在创建该实例的时候就提供,并在对象的整个生命周期(lifetime)内固定不变。其中常用的 String、基本类型包装类、BigInteger和BigDecimal 就是不可变类。
为了使类变成不可变,要遵循下面五条规则:

  • 不要提供任何回修改对象状态的方法
  • 保证类不会被扩展,即不会有方法重写
  • 声明所有的域都为final
  • 声明所有的域都为私有
  • 确保对于任何可变组件的互斥访问

代码示例

// Immutable complex number class (Pages 81-82)
public final class Complex {
    private final double re;
    private final double im;

    public static final Complex ZERO = new Complex(0, 0);
    public static final Complex ONE  = new Complex(1, 0);
    public static final Complex I    = new Complex(0, 1);

    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }

    public double realPart()      { return re; }
    public double imaginaryPart() { return im; }

    public Complex plus(Complex c) {
        return new Complex(re + c.re, im + c.im);
    }

    // Static factory, used in conjunction with private constructor (Page 85)
    public static Complex valueOf(double re, double im) {
        return new Complex(re, im);
    }

    public Complex minus(Complex c) {
        return new Complex(re - c.re, im - c.im);
    }

    public Complex times(Complex c) {
        return new Complex(re * c.re - im * c.im,
                re * c.im + im * c.re);
    }

    public Complex dividedBy(Complex c) {
        double tmp = c.re * c.re + c.im * c.im;
        return new Complex((re * c.re + im * c.im) / tmp,
                (im * c.re - re * c.im) / tmp);
    }
}

我们注意上述类的算数运算都是返回一个新的对象,大多数重要的不可变类都使用了该模式。它被称为函数的方法(functional approach)

优点

  • 不变对象比较简单,他只有一种状态,即被创建时的状态
  • 不可变对象本质上是线程安全的,它不要求同步
  • 不仅可以共享不可变对象,还可以共享它们内部的信息
  • 不可拜年对象为其他对象提供了大量的构件
  • 不可变对象无偿地提供了失败的原子性

缺点

  • 不可变类真正唯一的缺点是,对于每个不同的值都需要一个单独的对象,创建这些对象的代价可能很高。

技巧

可以使用静态工程来代替公有的构造器

public final class Complex {
    private final double re;
    private final double im;
    
	private Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }
	public static Complex valueOf(double re, double im) {
		return new Complex(re, im);
	}
    
  • 优先使用不可变类,只有当性能确实有要求时才需要为不可变类提供对应的可变类
  • 对于可变类,因尽可能限制可变性
  • 优先使用private final
  • 不要在构造器或者静态工厂之外再提供公有的初始化方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值