Reputation: 3234
I'm studying Effective Java by Joshua Bloch, where he explains about different ways of achieving immutable class. To prevent subclassing, one way is to use 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.
Upvotes: 1
Views: 834
Reputation: 85779
The only way a class cannot be subclassed is if the class is marked as final
. Since this class is not final
, then it can be subclassed, like this:
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);
}
}
Upvotes: 1
Reputation: 8297
As far as I remember Joshua then talks about EnumSet (but I do not remember context where he mentions it).
EnumSet
is abstract and also has static methods of, noneOf, etc.
There are two classes extending EnumSet
: JumboEnumSet
and RegularEnumSet
.
You cannot use them directly because they are package-private (no public
keyword):
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).
You simply use static methods of EnumSet
and it returns some subclass of EnumSet
you should not be aware of.
Take a look at the noneOf
method implementation:
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
Upvotes: 2