1

我正在研究 Joshua Bloch 的 Effective Java,他解释了实现不可变类的不同方法。为了防止子类化,一种方法是使用final。更复杂的方法是将构造函数设为私有,从而防止外部访问,并使用静态工厂创建对象。

但是,我不明白这个说法:

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

它是最灵活的,因为它允许使用多个包私有实现类。

我知道在没有公共/受保护的构造函数的情况下,外部客户端不可能对其进行子类化,但不理解术语“多包私有实现类”所传达的内容。

注意:这是有效 Java 中的第 15 条(最小化可变性)。

4

2 回答 2

2

据我所知,Joshua 然后谈到了EnumSet(但我不记得他提到它的上下文)。

EnumSet是抽象的,也有静态方法noneOf等。有两个类扩展EnumSetJumboEnumSetRegularEnumSet

您不能直接使用它们,因为它们是包私有的(无public关键字):

class RegularEnumSet<E extends Enum<E>> extends EnumSet<E>
class JumboEnumSet<E extends Enum<E>> extends EnumSet<E>

java.utilpackage only 可以直接使用它们(如果我们不谈论反射或其他一些技术)。

您只需使用静态方法,EnumSet它就会返回一些EnumSet您不应该知道的子类。

看一下noneOf方法实现:

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
    Enum<?>[] universe = getUniverse(elementType);
    if (universe == null)
        throw new ClassCastException(elementType + " not an enum");

    if (universe.length <= 64)
        return new RegularEnumSet<>(elementType, universe);
    else
        return new JumboEnumSet<>(elementType, universe);
}

这是多个包私有实现

于 2017-11-28T12:39:48.393 回答
1

不能对类进行子类化的唯一方法是将该类标记为final. 既然这个类不是final,那么它可以被子类化,像这样:

public class Complex {

    private final double re;
    private final double im;

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

    //methods...

    static class SubComplex1 extends Complex {

        private SubComplex1(double re, double im, double x) {
            super(re, im);
            //more elements...
        }
        //you can define/override methods here
    }

    public static Complex valueOf(double re, double im, double x) {
        return new SubComplex1(re, im, x);
    }
}
于 2017-11-28T12:36:15.923 回答