(15):使可变性最小化

不可变类只是其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个生命周期内固定不变。为了使类成为不可变,要遵循下面五条规则:

(1)不要提供任何会修改对象状态的方法

(2)保证类不会被扩展

(3)使所有的域都是final的

(4)使所有的域都成为私有的

(5)确保对于任何可变组件的互斥访问。

public final class Complex{
    private final double re;
    private final double im;

    public Complex(double im, double re) {
        this.im = im;
        this.re = re;
    }
    
    public double realPart(){
        return re;
    }
    
    public double imaginaryPart(){
        return im;
    }
    
    public Complex add(Complex c){
        return new Complex(re+c.re,im+c.im);
    }
    
    public Complex subtract(Complex c){
        return new Complex(re-c.re,im-c.im);
    }
    
    public Complex multiply(Complex c){
        return new Complex(re*c.re-im*c.im,im*c.re+im*c.re);
    }
    
    public Complex divide(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);
    }
}
这个类表示一个复数,该类提供了加减乘除四种运算,值得注意的是这四个函数都是返回新的对象,而不是修改原有对象。大多数不可变类都采用了这种模式。这种方式保证了每个对象的不可变性,但同时也带来了性能上的问题。

不可变对象本质上是线程安全的,它们不要求同步。所以不可变对象可以自由地共享。
不仅可以共享不可变对象,甚至也可以共享它们的内部信息。
不可变对象为其他对象提供了大量的构件,无论是可变的还是不可变的对象。
不可变类真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。创建这种对象的代价可能很高,特别是对于大型对象的情形。
为了确保不可变性,类绝对不允许自身被子类化。除了“使类成为final的”这种方法之外,还有另一种更加灵活的办法可以做到这一点。让不可变的类变成final的另一种办法就是,让类的所有构造器都变成私有的或者包级私有的,并添加公有的静态工厂来代替公有的构造器。

public class Complex{
    private final double re;
    private final double im;

    private Complex(double im, double re) {
        this.im = im;
        this.re = re;
    }
    
    public static Complex valueOf(double re,double im){
        return new Complex(re,im);
    }
}
总之,坚决不要为每个get方法编写一个相应的set方法。除非有很好的理由也要让类成为可变的类,否则就应该是不可变的。
对于有些类而言,其不可变性是不切实际的。如果类不能被做成是不可变的,仍然应该是尽可能地限制它的可变性。降低对象可以存在的状态数,可以更容易地分析该对象的行为,同时降低出错的可能性。因此,除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值