Question and scenario
Java 25 finalizes Flexible Constructor Bodies (JEP 513). Explain what may run before an explicit super(...) or this(...), why the object under construction cannot be read, and how the feature affects inheritance and argument preprocessing.
What the interviewer is testing
- Understanding constructor chains and the safety rule that the instance is not initialized yet.
- Distinguishing allowed static or local logic from illegal access to
this. - Recognizing preview versus final versions and source/target migration risk.
Clarifying questions before answering
Clarify whether the target is the final JDK 25 feature or an earlier JEP 447/482/492 preview, plus the project's source, target, and runtime versions. Clarify whether the focus is syntax, JVM verification, or inlining a helper that prepares super(...) arguments.
30-second answer framework
Traditional Java requires the first constructor statement to be super(...) or this(...). Flexible Constructor Bodies allow a restricted prologue before that invocation, such as computing locals or initializing fields of the current class, but code cannot read or call the instance under construction or pass an uninitialized this to arbitrary code. This enables direct argument preprocessing while preserving safe superclass construction order.
Step-by-step deep answer
- A constructor has a prologue, an explicit constructor invocation, and the remaining body.
this(...)continues the current-class chain;super(...)enters the parent. - The prologue may declare locals, evaluate expressions independent of instance state, and initialize fields of the current class that are still uninitialized. Those values may feed constructor arguments.
- It cannot read instance fields, call instance methods, use
thisas an argument, or expose a partially initialized object to observable code. - The compiler and JVM track which fields remain uninitialized so a superclass constructor cannot observe an invalid initialization order. Static methods and constants are usable where the rules permit.
- During migration, remove a helper only when it existed solely to prepare
super(...)arguments; keep helpers with side effects, multiple callers, or independent test value. - Compile and run with the JDK 25 toolchain. A project targeting an older source/target cannot simply adopt the syntax.
class Child extends Parent {
private final String normalized;
Child(String raw) {
var value = raw.trim(); // prologue: local computation
super(value); // explicit constructor invocation
this.normalized = value;
}
}High-quality sample answer
JEP 513 allows a restricted prologue before super(...) or this(...). It is useful for argument preprocessing and current-class field initialization that do not depend on instance state, but it still forbids reading fields, calling instance methods, or exposing an uninitialized this. The compiler and JVM preserve the guarantee that the superclass sees only legal initialization state. I would distinguish JEP 447/482/492 previews from the JDK 25 final feature and check source, target, and runtime versions. The feature reduces one-off static helpers without removing constructor-order or inheritance-safety constraints.
Common errors
- Saying that any statement may appear before
super(). - Ignoring that
thisis not initialized and allowing instance reads or calls. - Calling a preview JEP number the final JDK 25 number.
- Editing source without checking compiler target and deployment runtime.
- Adding externally observable side effects to the prologue for a convenient example.
Follow-up questions and responses
Why allow local computation but not reading this?
Local computation cannot observe a partially initialized object. Field reads or method calls can trigger dynamic dispatch, expose incomplete state, or let superclass logic see broken invariants.
Are the rules before this(...) and super(...) identical?
Both are constrained by the early-construction context. this(...) continues the current-class chain and super(...) enters the parent, but neither may expose instance state before legal initialization.
When should you keep the old helper instead of inlining it?
Keep it when it has multiple callers, meaningful side effects, independent test value, or a clear module boundary. The feature is a language capability, not a refactoring mandate.
How do you support older JDKs?
An older source/target cannot use the new syntax. Keep the existing argument-preparation approach until the compiler, runtime, and release matrix are upgraded together.