Static Factories and Builders
Source: Effective Java, 3rd Edition — Chapter 2 by Joshua Bloch (Items 1–5)
This chapter is about creating and destroying objects: when to create them, when not to, and how to hand off the dependencies they need. Items 1–5: static factories, builders, singletons, noninstantiable utilities, and dependency injection.
Item 1: Prefer static factory methods
A static factory method is a public static method that returns an instance. Not the Gang-of-Four “Factory Method” pattern — just a named static that hands you an object.
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
Advantages
- Names.
BigInteger.probablePrime(...)beats a three-arg constructor nobody can decode. Same signature twice? Give each factory a clear name instead of swapping parameter order (a trap). - Need not create a new object. Immutable types can cache / reuse (
Boolean.TRUE). Instance-controlled classes: singleton, noninstantiable, or “a.equals(b)iffa == b” (Flyweight). Enums do this for free. - Return any subtype of the declared type. Keep implementation classes package-private; clients code to the interface (
Collections.unmodifiableList). Before Java 8, factories lived in a companionTypesclass; now many sit on the interface (Java 9: private static methods allowed; static fields on interfaces are still public). - Return type can depend on the arguments (and change across releases).
EnumSet.of(...)picksRegularEnumSetvsJumboEnumSetby enum size — clients never see those names. - Returned class need not exist yet — service-provider frameworks (JDBC:
Connection,DriverManager.registerDriver/getConnection,Driver). PreferServiceLoadertoday unless you are stuck on legacy APIs.
Costs
- No public/protected constructor → cannot subclass (often good: push composition, Item 18; required for many immutables).
- Harder to discover in Javadoc than constructors. Document them and use common names:
| Name | Meaning |
|---|---|
from | convert one value |
of | aggregate many |
valueOf | verbose from/of |
getInstance / instance | described by params, not “same value” |
newInstance / create | new object each call |
getType / newType / type | factory lives in another class |
Constructors still have a place — just do not reach for a public constructor on reflex.
Static factories
1 / 2Boolean.valueOf(true) called twice
Pick an answer to see if you are right.
Item 2: Prefer a builder for many parameters
Optional fields explode. Three bad/good options:
Telescoping constructors
NutritionFacts(size, servings), then add calories, fat, … — does not scale. Call sites pass dummy zeros; identical ints get swapped silently.
JavaBeans
Empty constructor + setters. Readable, but the object is mutable, can be half-built, and hard to keep consistent or thread-safe. “Freeze” APIs are awkward.
Builder
Required args in Builder(...); optional chainable setters return this; build() produces an immutable instance. Fluent and self-documenting:
NutritionFacts cola = new NutritionFacts.Builder(240, 8)
.calories(100).sodium(35).carbohydrate(27).build();
Validate early in builder setters; multi-field invariants in the private constructor after copying from the builder. Hierarchies: abstract Pizza.Builder<T extends Builder<T>> + self() (simulated self-type) and covariant build() in subclasses (NyPizza, Calzone).
Cost: an extra object; more code than a short telescoping list. Worth it around four or more parameters, especially optional or same-typed. Starting with a builder beats shipping telescoping APIs you later regret.
Item 3: Enforce a singleton
Exactly one instance. Harder to mock unless the type is an interface.
public static finalfield + private constructor — clearest API, simplest.getInstance()static factory — can later change policy (per-thread, etc.); works as a method referenceElvis::getInstance.- Single-element enum — preferred: concise, serialization-safe, reflection-resistant. Cannot extend another class (can implement interfaces).
Serializable field/factory singletons need transient fields + readResolve() returning INSTANCE, or deserialization creates clones.
Item 4: Noninstantiable utility classes
Math, Arrays, Collections: static groups only. Making the class abstract fails — someone subclasses and constructs. Suppress the default constructor:
public class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
Side effect: no subclasses (no accessible super constructor).
Noninstantiable utility classes
1 / 2A class like Math or Collections that only holds static methods
Pick an answer to see if you are right.
Item 5: Prefer dependency injection
Do not hard-wire a Lexicon inside a static utility or singleton SpellChecker. Languages, test dictionaries, and concurrency all break that assumption.
Inject the resource (or a Supplier<? extends Tile> factory) into the constructor / static factory / builder:
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
}
Simple, testable, immutable-friendly. Large graphs → Guice / Spring / Dagger — APIs designed for manual DI adapt cleanly.
Dependency injection
1 / 1SpellChecker that must work with many dictionaries
Pick an answer to see if you are right.
Chapter 2 so far
| Item | Move |
|---|---|
| 1 | Named static factories; cache; hide subtypes |
| 2 | Builder when optional/same-typed params pile up |
| 3 | Singleton via field, factory, or enum |
| 4 | Private constructor (+ AssertionError) for utilities |
| 5 | Inject resources; do not hard-wire them |
Next items pick up cleanup, avoid unnecessary objects, and more creation pitfalls.