Warm-up

final did not do what you think

5 minjunior16 yrs

One concept, guided. Near-impossible to fail.

What this teaches

  • final prevents reassignment of the variable, nothing more
  • A final field holding a collection is fully mutable
  • The two leaks are the constructor and the getter, and they are separate

Starter

Starter.javaOpen in playground
import java.util.*;

/**
 * WARM-UP — 5 minutes. One concept. Hard to fail.
 *
 * Every field is private final. There is not a single setter. The object is
 * modified twice anyway.
 *
 * TASKS
 *   1. Predict each printed line before running.
 *   2. Run it.
 *   3. Uncomment line (3). It will not compile — and the error tells you
 *      exactly what final DOES prevent. Comment it back out.
 *   4. Name the two leaks. They are in different methods and need
 *      different fixes.
 */
public class Starter {

    static final class Basket {
        private final String owner;
        private final List<String> items;

        Basket(String owner, List<String> items) {
            this.owner = owner;
            this.items = items;
        }

        List<String> items() {
            return items;
        }

        @Override
        public String toString() {
            return owner + " " + items;
        }
    }

    public static void main(String[] args) {
        List<String> caller = new ArrayList<>(List.of("keyboard"));
        Basket basket = new Basket("ravi", caller);

        System.out.println("as constructed  : " + basket);

        caller.add("added by the caller");
        System.out.println("caller mutated  : " + basket);

        basket.items().add("added by a reader");
        System.out.println("reader mutated  : " + basket);

        // (3) Uncomment. This is the only thing final was ever stopping.
        // basket.items = new ArrayList<>();

        // Question to answer in a comment before you move on:
        // Nobody reassigned `items`. So what, exactly, did final guarantee —
        // and was it ever going to help here?
    }
}

Run it locally:

cd exercises/java/oop/immutability-in-practice/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out Starter

Done when

  • You predicted which line would fail to compile and which would succeed
  • You identified both leaks by name before being told
  • A comment says what final actually guaranteed here

← Back to How do you make a class genuinely immutable?