Java Interview Question - The Hidden Object Construction Bug in Java
When Initialization Lies 🤥
Context (Production Scenario)
You are working on a backend service that processes user profiles.
The system has a base class that standardizes logging for all domain objects.
Current Implementation
Usage
Expected Output
User: aliceActual Output
User: null📢 Get actionable Java and Spring Boot insights every week, including practical code tips and real-world, use-case-based interview questions, to help you level up your backend skills—join 7000+ subscribers for hand-crafted, no-fluff content.
First 100 paid subscribers will get the annual membership at $50/year forever that is ~ $4/mo ( 84 already converted to paid, 16 sport remaining)
Testimonials
Why is
usernamenull inlogState()?
This happens mainly because of Java object construction order + method overriding during construction.
When we do:
new User("alice");Java doesn’t fully build user object first. Instead the construction happens like this:
A
Userobject is created in heap:username = null (default value)Base class constructor BaseEntity() runs first and Inside it we call
logState();Dynamic dispatch kicks in
Even though we are inside
BaseEntity, Java calls:User.logState()
because method overriding is runtime-polymorphic.
4. But User fields are not initialized yet
At this point, below initialization has not executed.
private String username = "guest";Also constructor body:
User(String username) {
this.username = username;
}has not run yet.
So state is: username = null
and hence the logger logs null for username.
So overall issue is
The base class constructor calls an overridden method, but subclass fields are not initialized yet.
This is called object escape during construction.
Why Java behaves like this?
Java behaves like this because it is trying to satisfy two design guarantees at the same time, and the combination creates this surprising behavior.
Superclass must initialize first
When we create a subclass object: new User();
Java enforces:
The superclass part of the object must be fully constructed before the subclass runs.
So order is always:
1. memory allocated
2. Base class constructor runs
3. subclass fields initialized
4. subclass constructor body runsThis guarantees:
base class invariants are established first
inheritance is safe and predictable
Polymorphism must always work
Java also guarantees:
Method overriding is always dynamic (runtime-based), even during construction.
So even inside BaseEntity constructor: logState();
Java does not bind it to BaseEntity.logState().
It resolves at runtime to: User.logState();
Now it combines both rules:
During Base constructor:
object is already a User instance
But User fields are not initialized yet
overridden methods are already active
So we get:
Fully typed object (User exists)
But partially initialized state (fields still default)Why do you think Java didn’t block overridden methods in constructors?
Java could have done this, but it would break:
Then:
polymorphism becomes inconsistent
frameworks relying on hooks would break
design patterns like Template Method would be limited
So Java chose:
“Keep polymorphism consistent everywhere, even if constructors become tricky.”
Mental model
Object creation is more like:
Step 1: object exists (identity is known)
Step 2: base class builds foundation
Step 3: subclass adds details
Step 4: object becomes safe to useBut Java allows method calls during Step 2 to already behave like Step 4 (polymorphism), which is where the confusion comes from.
How would you redesign this to avoid the bug?
Constructors should only initialize state, not execute polymorphic behavior.
So we should separate construction and behavior execution.
Option 1: Remove behavior from constructor
construction is separate from execution
no polymorphic call during initialization
object is fully built before behavior runs
Option 2: Explicit lifecycle method
construction = object creation only
initialization = explicit lifecycle step
behavior = safe after full state is ready
This is how:
Spring uses
@PostConstructHibernate uses lifecycle callbacks
frameworks avoid constructor logic
Instead of:
constructor → behaviorWe shift to:
constructor → initialize state → lifecycle hook → behaviorThats all for this week friends! Thanks for reading this far. If you liked it please share with your network.
Happy Coding 🚀
Suraj
Subscribe | Sponsor us | LinkedIn | Twitter









