Return to site

HEADS-UP FOR JDK 25: null-checks in inner class constructors 👇

· java25,java
Section image

Non-static inner classes always capture a reference to their enclosing instance. That reference is passed implicitly to the inner’s constructor and stored in a field. If that reference is ever null (via reflection, frameworks, bytecode gen, deserialization, etc.), you get a time-bomb NPE later.

WHAT’S NEW IN JAVA 25

- 🛡️ javac now injects a null-check in constructors of non-static inner classes.

- If the outer reference is null, construction fails immediately, not later.

EXAMPLE

class Outer {

class Inner { /* ... */ }

}

new Outer().new Inner(); // OK

// Forcing a null "outer" (reflection/bytecode hacks) now throws early in JDK 25.

WHY THIS MATTERS

- Earlier failure ⇒ easier debugging & safer invariants.

- Frameworks that craft instances should respect the invariant that the captured outer is non-null.

TEMPORARY ESCAPE HATCH (NOT RECOMMENDED)

- You can disable the injected check with:

javac -XDnullCheckOuterThis=false

Use only as a stop-gap while fixing code paths that smuggle null outers.

BEST PRACTICE

- Prefer static nested classes when you don’t need an outer instance.

- If you do need a non-static inner, never construct it without a real Outer:

Outer outer = new Outer();

Outer.Inner inner = outer.new Inner();

This is one of those “fail fast, fail loud” changes that makes codebases sturdier. 💪

#Java25 #JDK25 #Java #javac #NullSafety #InnerClasses #CleanCode #Refactoring