Effective Java

Idioms and patterns for effective Java programming

June 6, 2001-- At Tuesday's "Effective Programming with Java Technology" conference session (TS-2425), Joshua Bloch, senior staff engineer from Sun Microsystems, presented some powerful, but not well known, idioms that should improve the effectiveness and quality of your Java programming. These idioms were taken directly from Bloch's new book, Effective Java Programming Language Guide (Addison-Wesley, 2001).

Bloch's session covered:

  • The Static Factory pattern
  • The Singleton pattern
  • The Utility Class idiom
  • The Typesafe Enumeration pattern
  • Effective random number generation

The Static Factory pattern

When you want to create an instance of a class (an object), you normally do so by calling new on the class's constructor. As an alternative to new, the Static Factory pattern provides a static method that returns an instance.

Bloch took the following example of a static factory straight from Java:

public static Boolean valueOf(boolean b) {
    return (b ? Boolean.TRUE : Boolean.False);
}

This method appears in the java.lang.Boolean class.

Static Factory pattern advantages

Bloch noted a number of advantages to using static factories instead of constructors to create objects.

First, static factories have names while constructors do not. Constructors must have the same name as the class and may vary only in their type and number of arguments. Static factories, on the other hand, can have different names, as well as any type and number of arguments. Bloch used an example of a complex number to drive this point home:

public static Complex valueOf(float re, float im) //...
public static Complex valueOfPolar(float r, float theta) // ...

In the code above, the static factory is much more expressive. Furthermore, the equivalent constructors would have conflicted with one another, since they would have the same number and argument types.

Second, Bloch explained that a static factory is not required to create a new object each time it is called. This means that you can reuse immutable objects and cache frequently used values (such as Boolean's TRUE and FALSE). Such reuse can lead to improved performance. With static factories, you can also control and regulate which objects exist at any given time. You can't do that with new.

Finally, Bloch pointed out that static factories can return objects of any subtype. Creating an object using a constructor will only create objects of a specific type. Using a static factory in this way creates a nice separation between interface and implementation. Beyond supporting polymorphism, the ability to hide an object's subtype is powerful. The class of the object that is returned need not be public, leading to compact, easier-to-understand APIs. The result: it's easier to make changes to the API from release to release, and even during runtime.

Static Factory pattern disadvantages

As useful as it is, the static factory does have some disadvantages.

Bloch explained that a static factory cannot be subclassed. Normally, a static factory will make its constructor private so that other objects cannot instantiate it directly. However, Bloch maintained, this is a blessing in disguise, since inheritance is not always the best form of reuse anyway.

Bloch also cautioned that static factory methods are indistinguishable from other methods. To effectively use the pattern, you need to establish and follow an effective naming convention.

Bloch recommends that you employ the Static Factory pattern when you don't need to subclass the class and one or more of the following proves true:

  • Using the pattern will produce a significant performance gain
  • You need the flexibility to return different types without the other objects needing to know the returned object's true type
  • You want to avoid making a class public
  • You need control over the instances

The Singleton pattern

While every developer is familiar with the Singleton pattern, Bloch presented the pattern with a fresh, Java-centric approach. Here's the example he used:

public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() {
        // ....
    }
}

Indeed, there is and will be only one Elvis.

A singleton possesses no accessible constructor. Rather, it allows you to gain a reference to the singleton via a static final instance field. What makes the singleton interesting in Java is its serialization mechanism. If you are not careful, serializing an object can result in multiple instances!

Bloch presented a workaround. You can simply override readResolve()as follows:

private Object readResolve() throws ObjectStreamException {
    return INSTANCE;
}

The Utility Class idiom

A utility class contains only public static methods and is not meant to be instantiated. Utility classes are easily abused and can lead to procedural programming. However, Bloch pointed out two valid uses of this idiom. You should use a utility class to act on collections of primitives and collections of objects that implement interfaces. java.util.Collections serves as an example of a properly designed utility class.

Utility classes take the following form:

public class UtilityClass {
    // made private so cannot instantiate
    private UtilityClass() {}
    public static method() { /... and so on
}

The Typesafe Enumeration pattern

Java lacks an enumerated type. The Typesafe Enumeration pattern presents an alternative that replaces non-type safe constants with a type safe enumeration. Unfortunately, you cannot use these enumerations in switch statements.

For Bloch's explanation on the Typesafe Enumeration pattern, see chapter five of his book, Effective Java Programming Language Guide.

Effective random number generation

Finally, Bloch recommended that developers use java.lang.Randomto create random numbers, as other procedures may not work effectively. Random, added in Java 1.2, fixes some serious flaws found in the old random number generators.

Tony Sintesis a principal consultant at BroadVision. Tony, a Sun-certified Java 1.1 programmer and Java 2 developer, has worked with Java since 1997.

Learn more about this topic

Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more