Warm-up

Delete a case and read the error

5 minjunior16 yrs

One concept, guided. Near-impossible to fail.

What this teaches

  • A switch over a sealed type needs no default branch
  • Removing a case turns a runtime bug into a compile error
  • Exhaustiveness depends on the selector's static type, not on the value

Starter

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

/**
 * WARM-UP — 5 minutes. One concept. Hard to fail.
 *
 * A closed set of three payment types, and a switch with no default.
 *
 * TASKS
 *   1. Run it. Nothing surprising yet.
 *   2. Delete the `case Cash` line. Compile. Read the error out loud.
 *   3. Put it back. Now change describe's parameter from Payment to Object
 *      and compile again. Same error, different reason — work out which.
 *   4. Change it back, and answer in a comment: if this switch had a
 *      `default -> throw new IllegalStateException()`, what would step 2
 *      have produced instead of a compile error?
 */
public class Starter {

    sealed interface Payment permits Card, Upi, Cash {}

    record Card(String network, int lastFour) implements Payment {}

    record Upi(String handle) implements Payment {}

    record Cash(BigDecimal amount) implements Payment {}

    static String describe(Payment payment) {
        return switch (payment) {
            case Card(String network, int last) -> network + " ending " + last;
            case Upi(String handle) -> "UPI " + handle;
            case Cash c -> "cash " + c.amount();
        };
    }

    public static void main(String[] args) {
        List<Payment> payments = List.of(
                new Card("visa", 4242),
                new Upi("ravi@okhdfc"),
                new Cash(new BigDecimal("250.00")));

        for (Payment payment : payments) {
            System.out.println(describe(payment));
        }

        // Bonus: Payment.class.getPermittedSubclasses() is a real runtime
        // call. Print it. Where is that list stored, and who enforces it?
    }
}

Run it locally:

cd exercises/java/modern-java/sealed-classes/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out Starter

Done when

  • You removed a case, read the error, and put it back
  • You changed the parameter to Object and explained why it then needs a default
  • A comment states what the default branch would have cost you

← Back to What do sealed classes enable that abstract classes cannot?