Generics

Generics Best Practices

The Effective Java generics doctrine in one place: no raw types, no unchecked warnings, lists over arrays, generify your own APIs, PECS at boundaries, and type tokens when runtime types are unavoidable.
  • Don't use raw types (26); eliminate unchecked warnings (27)
  • Prefer lists to arrays in APIs (28)
  • Favor generic types (29) and generic methods (30)
  • Bounded wildcards for flexible APIs — PECS (31)
  • Combine generics and varargs judiciously — @SafeVarargs (32)
  • Typesafe heterogeneous containers via Class<T> keys (33)
Effective Java Chapter 5 at a glance
ItemRuleSound bite
26No raw typesRaw types opt out of the entire type system
27No unchecked warningsEvery warning is a deferred ClassCastException
28Lists over arraysFail at compile time, not at runtime
29Generify your classesCasts in client code are your API's failure
30Generify your methodsInference makes them free to call
31Bounded wildcardsPECS: producer-extends, consumer-super
32Varargs with care@SafeVarargs, or take a List instead
33Type tokensClass<T> keys make containers heterogeneous AND safe
Typesafe heterogeneous container (EJ Item 33)
public class Favorites {
    private final Map<Class<?>, Object> favorites = new HashMap<>();

    public <T> void put(Class<T> type, T instance) {
        favorites.put(Objects.requireNonNull(type), type.cast(instance));
    }

    public <T> T get(Class<T> type) {
        return type.cast(favorites.get(type));   // dynamic cast — provably safe
    }
}

Favorites f = new Favorites();
f.put(String.class, "Java");
f.put(Integer.class, 42);
String s = f.get(String.class);   // no cast in client code

The container works because the key carries the type: Class<T> is a parameterized type token, and Class.cast is a checked, type-safe cast. The same idea powers annotation lookups (getAnnotation(Class<A>)) and dependency-injection frameworks.

Sources
  • Effective Java (3rd ed.)Items 26–33
  • Core Java, Volume I: Fundamentals (13th ed.)Ch. 8 — Generic Programming