Study notes @Effective Java
The content of the article comes from the book Joshua Bloch-Effective Java (3rd)-2018.chm
Chapter two
Create and unregister objects
Item 4 that cannot be instantiated must have a Private constructor
Enforce noninstantiability with a private constructor
Sometimes you want to write a class that contains only a set of static methods and static fields
Such kind of criticism in the industry, as far as the object is concerned, because some people use it without a brain, but they do have effective uses
- They can group related methods using primitive values or arrays, using java.lang.Math or java.util.Arrays
- They can also be used to group static methods of objects that implement certain interfaces, using the java.util.Collections file
- Or, these classes can be used to group methods into final classes because you cannot put them in subclasses
- (Java8 and later, you can also put these methods in the interface, if you modify these methods)
Such utility classes are not designed to be instantiated: an example of this kind is meaningless
However, in the absence of an explicit constructor, the compiler provides a public, parameterless default constructor
For users, this constructor is no different from any other constructor
It is not uncommon to accidentally see instantiable classes in published APIs
Trying to enforce non-instantiable by making the class abstract will not work
The class can be a subclass, and the subclass can be instantiated
In addition, it misleads users into thinking that the class is designed for inheritance
However, there is a simple usage to ensure non-instance
The default constructor will only be generated when the class does not have an explicit constructor, so
You can make the class non-instantiable by including a private constructor:
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}
Because the explicit constructor is private, it is not accessible outside the class
The error AssertionError is not strictly required, but it provides an insurance method to prevent accidental transfer of the constructor from the class
It guarantees that the class will not be instantiated under any circumstances
This idiom is a bit counterintuitive, because the constructor is explicitly provided and cannot be called yet
So like the above example, it is wise to add comments
As a side effect, this idiom also prevents classes from being subclassed
(Under normal circumstances) all constructors must call the parent class constructor, explicit or implicit, (but in this case) the child class will have no accessible parent class constructor to call