bhylu.com

Advertisements

Java Restrict a Type Family and Handle Every Case

A sealed type can restrict which implementations belong to a small domain family. Pattern matching can then express a result for each permitted shape without unsafe casts.

Understand the idea

Use a closed family only when the domain really has a controlled set of variants. A permitted subtype must follow the sealed, non-sealed or final requirements. Records are final, making them convenient immutable-style variants. Java 21 supports final pattern matching for switch, so the shown example needs no preview flags. Adding a new permitted subtype may require callers to update exhaustive switches.

Run it locally

Use a local JDK 21 or newer. Save the complete example as Main.java in a separate lab folder, then compile and run it with the commands below. Java examples do not run in Bhylu’s browser playground. The -ea option enables assertion checks used by some lessons.

JDK and terminal setup

javac --release 21 -encoding UTF-8 -d out Main.java
java -ea -cp out Main

A worked example

Java 21+ · Main.java

public class Main {
    sealed interface Price permits Flat, PerSeat {}
    record Flat(int cents) implements Price {}
    record PerSeat(int cents) implements Price {}

    public static void main(String[] args) {
        Price price = new PerSeat(325);
        int amount = switch (price) {
            case Flat flat -> flat.cents();
            case PerSeat perSeat -> perSeat.cents() * 4;
        };
        System.out.println(amount);
    }
}

Expected output

1300

The matched pattern provides a typed local binding, so the selected case can read cents without an explicit cast. The two cases cover the permitted non-null variants. A null selector still needs its own policy; exhaustiveness over permitted subtypes does not automatically mean a missing value is accepted.

Check the official Java documentation for detailed contracts and supported options.