Parents first, and final fields¶
โ Java 17 ยท The Order Java Builds Your Objects In ยท 3/4
Objects are built in layers: the parent part first, then the child part. Here is how constructors make that happen.
Parents are built before children¶
class Content {
Content() { System.out.print("Content-"); }
}
class Movie extends Content {
Movie() { System.out.print("Movie1-"); }
Movie(int y) { System.out.print("Movie2-"); }
}
class Trailer extends Movie {
Trailer() {
super(2026);
System.out.print("Trailer-");
}
}
// new Trailer();
Output:
Always start from the new call:
Trailer()callssuper(2026), soMovie(int)runs.Movie(int)has no explicit first line: the compiler addssuper();, soContent()runs.- The bodies then finish top-down:
Content, thenMovie2, thenTrailer.
Constructors are called bottom-up, but their bodies run top-down. Only constructors on the real path run: Movie() is never called, so Movie1- never prints.
Since every constructor on the path runs, each one has a responsibility toward final fields.
Final fields: set once, never twice¶
A final instance field must be assigned exactly once โ never zero times, never twice.
This version does not compile:
class Episode {
private final String title;
private final int season = 1;
Episode() { season = 2; } // โ season assigned twice, title never
}
seasonalready gets1on its declaration, soseason = 2is a second assignment.- This constructor never assigns
title.
This version compiles:
class Episode {
private final String title;
private final int season = 1;
Episode(String t) { title = t; }
Episode() { this(null); } // โ
delegates to the first constructor
}
A final field can be assigned in three places: on its declaration, in an instance block, or in a constructor. The compiler checks each constructor separately: every path must leave every final field assigned once. null is a valid value, as long as you assign it.
You now have the whole picture. Time to see it run.