Skip to content

Lab: booting the streaming catalog

☕ Java 17 · The Order Java Builds Your Objects In · 4/4

Goal: make every piece of setup code print a numbered message, so the program shows its own initialization order.

Setup: create StreamingCatalog.java (no package). All classes go in this one file. Compile and run it with javac StreamingCatalog.java then java StreamingCatalog.

Step 1 — The parent class alone

class Content {
    static void log(String message) { System.out.println(message); }
    static { log("1. Content class loaded"); }
    { log("3. Content fields ready"); }
    Content() { log("4. Content built"); }
}

public class StreamingCatalog {
    public static void main(String[] args) {
        System.out.println("Opening the catalog");
        new Content();
    }
}

log is a small static helper so every step prints the same way. Number 2 is skipped on purpose: it belongs to Movie.

Opening the catalog
1. Content class loaded
3. Content fields ready
4. Content built

Opening the catalog comes before the class is loaded: a class is set up the first time it's needed, here at new Content().

Step 2 — Add the child class

Add Movie between Content and StreamingCatalog:

class Movie extends Content {
    static { log("2. Movie class loaded"); }
    private final String title;
    { log("5. Movie fields ready"); }
    Movie(String t) { title = t; log("6. Movie built: " + t); }
}

In main, replace new Content(); with:

Movie dune = new Movie("Dune");
Opening the catalog
1. Content class loaded
2. Movie class loaded
3. Content fields ready
4. Content built
5. Movie fields ready
6. Movie built: Dune
  • 1–2: class setup, parent before child.
  • 3–6: object setup, the Content part then the Movie part. The compiler's hidden super() in Movie(String) is what builds the Content part first.
  • The final title is assigned exactly once, in the constructor.

Step 3 — Create a second movie

Add at the end of main:

System.out.println("--- second movie ---");
Movie arrival = new Movie("Arrival");
...
6. Movie built: Dune
--- second movie ---
3. Content fields ready
4. Content built
5. Movie fields ready
6. Movie built: Arrival

Messages 1 and 2 don't come back: both classes are already set up. Messages 3 to 6 run again, because instance blocks and constructors run on every new.

Final code

class Content {
    static void log(String message) { System.out.println(message); }
    static { log("1. Content class loaded"); }
    { log("3. Content fields ready"); }
    Content() { log("4. Content built"); }
}

class Movie extends Content {
    static { log("2. Movie class loaded"); }
    private final String title;
    { log("5. Movie fields ready"); }
    Movie(String t) { title = t; log("6. Movie built: " + t); }
}

public class StreamingCatalog {
    public static void main(String[] args) {
        System.out.println("Opening the catalog");
        Movie dune = new Movie("Dune");
        System.out.println("--- second movie ---");
        Movie arrival = new Movie("Arrival");
    }
}

Full code on GitHub

← Parents and final fields · Back to the series


🎓 Preparing the OCP Java 17 exam? Exam traps and practice questions for this section → (optional)