Saturday 22 November 2008

tem 4: Enforce non-instantiability with a private constructor

Once in a while, a Java programmer will want to create a utility class that has only static members. For example, java.lang.Math is one such class. In C++, we could simply write a set a free functions inside a namespace. Java, on the other hand, mandates that everything must be a class member, and this gives rise to this kind of class, where everything inside it is static, which seems like a bit of a hack to me.

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: