Skip to main content

Varargs, Returns, and Documentation

Source: Effective Java, 3rd Edition — Chapter 8 by Joshua Bloch (Items 53–56)

This lesson closes Chapter 8: varargs, returning empty containers and optionals, and Javadoc for exported APIs.

Item 53: Use varargs judiciously​

Varargs (int... args) build an array at each call site. Fine for printf, reflection, and variable-arity utilities like sum(int... args).

Wrong for “one or more” arguments:

static int min(int... args) { if (args.length == 0) throw ... } // fails at runtime if empty

Right: require at least one ordinary parameter, then varargs for the rest:

static int min(int firstArg, int... remainingArgs) { ... }

Every varargs call allocates an array — in hot paths, overload foo(), foo(int), … foo(int,int,int,int...) like EnumSet factories (Item 36). Do not overload varargs methods except as in Item 52.

Item 54: Return empty collections or arrays, not nulls​

Returning null for “no results” forces every caller to null-check — easy to forget, and errors surface far from the bug.

// Don't
return cheesesInStock.isEmpty() ? null : new ArrayList<>(cheesesInStock);

// Do
return new ArrayList<>(cheesesInStock);

If profiling shows empty allocations matter, reuse Collections.emptyList() / emptySet() / emptyMap() (immutable, shareable). For arrays: toArray(new Cheese[0]), or a shared EMPTY_ARRAY. Do not preallocate toArray(new T[size]) for performance (counterproductive).

Quiz

Empty collections

1 / 2

getCheeses returns null when the shop has no cheese

Pick an answer to see if you are right.

Item 55: Return optionals judiciously​

Optional<T> (Java 8) models “maybe a value” without null returns or exceptions for ordinary absence. Use when a method may have no result and callers must explicitly handle that case.

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
if (c.isEmpty()) return Optional.empty();
...
return Optional.of(result);
}

Never return null from an Optional-returning method. Clients use orElse, orElseThrow, orElseGet, map, flatMap. For primitives use OptionalInt etc., not Optional<Integer>.

Do not wrap collections/maps in optionals (return empty container, Item 54). Optionals are primarily return types, not fields/map values (exceptions like optional getters on rich DTOs exist).

Item 56: Write doc comments for all exposed API elements​

Document every exported class, interface, constructor, method, and field with Javadoc (/** ... */). Describe the contract (what, not how): preconditions, postconditions, side effects.

Include for methods:

  • @param for each parameter
  • @return unless void (unless redundant by your style guide)
  • @throws for every thrown exception (if clause after the tag)

Use {@code ...} for inline code, {@literal ...} for HTML metacharacters, {@implSpec} for inheritance self-use (Item 19). Summary sentence: verb phrase for methods, noun phrase for types/fields. Document enum constants, generic @param <T>, and annotation members.

Quiz

Javadoc

1 / 2

Exported method with no doc comment

Pick an answer to see if you are right.

Items 53–56 map​

ItemMove
53Varargs for 0+; required param + varargs for 1+
54Empty collections/arrays, not null
55Optional for absent results; not for containers
56Javadoc every exported API; @param @return @throws

Chapter 8 complete. Next: Scope, Loops, and Types (Chapter 9, Items 57–62).