简体   繁体   English

使用静态工厂的不可变类

[英]Immutable class using static factories

I'm studying Effective Java by Joshua Bloch, where he explains about different ways of achieving immutable class. 我正在学习Joshua Bloch的Effective Java,在那里他解释了实现不可变类的不同方法。 To prevent subclassing, one way is to use final . 为了防止子类化,一种方法是使用final The more sophisticated way for it is to make constructor private, thus preventing outside access, and using static factories for object creation. 更复杂的方法是将构造函数设为私有,从而防止外部访问,并使用静态工厂进行对象创建。

However, I don't understand this statement: 但是,我不明白这句话:

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

It is most flexible because it allows the use of multiple package-private implementation classes. 它最灵活,因为它允许使用多个包私有实现类。

I understand that it's not possible for an outside client to subclass it in absence of a public/protected constructor, but do not understand what is being conveyed by the term 'multiple package private implementation classes'. 我理解外部客户端在没有公共/受保护构造函数的情况下将其子类化是不可能的,但是不理解术语“多包私有实现类”所传达的内容。

NOTE: This is Item 15 (Minimize mutability) in Effective Java. 注意:这是Effective Java中的第15项(最小化可变性)。

As far as I remember Joshua then talks about EnumSet (but I do not remember context where he mentions it). 据我记得约书亚然后谈论EnumSet (但我不记得他提到的背景)。

EnumSet is abstract and also has static methods of , noneOf , etc. There are two classes extending EnumSet : JumboEnumSet and RegularEnumSet . EnumSet是抽象的,也有静态方法noneOf等有两类扩展EnumSetJumboEnumSetRegularEnumSet

You cannot use them directly because they are package-private (no public keyword): 您不能直接使用它们,因为它们是包私有的(没有public关键字):

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

java.util package only can use them directly (if we do not speak about reflection or some other techinques). java.util包只能直接使用它们(如果我们不谈论反射或其他技术)。

You simply use static methods of EnumSet and it returns some subclass of EnumSet you should not be aware of. 您只需使用EnumSet静态方法,它就会返回一些您不应该注意的EnumSet子类。

Take a look at the noneOf method implementation: 看一下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);
}

Here is the multiple package-private implementations 这是多个包私有实现

The only way a class cannot be subclassed is if the class is marked as final . 类不能被子类化的唯一方法是将类标记为final Since this class is not final , then it can be subclassed , like this: 由于这个类不是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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM