Effective Java2读书笔记-类和接口(二)

第15条:使可变性最小化

  通过一个复数类来看不可变类。

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);
    }

    public static Complex valueOfPolar(double r, double theta) {
        return new Complex(r * Math.cos(theta), r * Math.sin(theta));
    }

    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 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, re * c.im + 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);
    }

    @Override
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Complex))
            return false;
        Complex c = (Complex) o;

        return Double.compare(re, c.re) == 0 && Double.compare(im, c.im) == 0;
    }

    @Override
    public int hashCode() {
        int result = 17 + hashDouble(re);
        result = 31 * result + hashDouble(im);
        return result;
    }

    private int hashDouble(double val) {
        long longBits = Double.doubleToLongBits(re);
        return (int) (longBits ^ (longBits >>> 32));
    }

    @Override
    public String toString() {
        return "(" + re + " + " + im + "i)";
    }
}
View Code

  复数类具有实部和虚部,它提供的加减乘除运算都是返回新的Complex实例,而不是修改这个实例。不可变对象有很多优点,它只有一种状态,即被创建时的状态,而且前面也提到过,它本质上是线程安全的。

  这里还用到一个小技巧,对频繁使用的值,为它们提供公有的静态final常量。

  还有一种构建不可变类的常用方法,让类的构造器私有化,并添加上公有静态工厂方法,前面也提到过。

  String类就是不可变类一个典型例子。但是细心的读者肯定会发现String类的hash属性不是final类型的,事实上,许多不可变类都拥有一个或多个非final的域,在第一次请求的时候计算出来缓存在这些域中,从而节约了计算所需要的花销。因为对象是不可变的,它的不可变性保证了计算结果相同。

public final class String{
    private final char value[];
    private int hash;

    public int hashCode() {
        int h = hash;
        //只有hash不存在时才去计算
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
}

第16条:复合优先于继承

  简而言之,只有当两者确实存在is-a的关系时,才使用继承。否则,都应该使用复合。对于这一条,应用最典型的例子就是设计模式中的装饰者模式

原文地址:https://www.cnblogs.com/ZhangWanFan/p/5297662.html