As it wouldn't make sense to instantiate such a class, it's good practice to make the class uninstantiable. Making it abstract doesn't work: it can be subclassed, and the subclass can be instantiated.
The solution is to define a private constructor. This prevents the compiler from providing a public default constructor, and also prevents the class from being subclassed. This is, in fact, the same idiom that is often used in C++ to control instances (as in Item 1). However, there is a difference. In C++, it is usual not to provide a body for the private constructor. In Java, every method must have a body - even the private constructor, which is intended never to be called! To prohibit accidental calling of the private constructor from another method in this class, it is common to make it throw an exception:
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
...
}
So, whereas in C++ an attempt to instantiate a non-instantiable class can be caught at link time, in Java it will only be caught during testing or, heavens forbidding, in production. This item has left me wondering what the rationale was for disallowing free functions, which would have eliminated the need for such utility classes. Is the "everything is a class member" restriction just part of the language, or is it part of the JVM? If it's the latter, I wonder how languages like Groovy implement free functions.
Klitos Kyriacou
No comments:
Post a Comment