Object-Oriented Programming
Nested Classes
Contrast Static Nested classes with non-static Inner classes, tracking enclosing instance reference leaks.
Interview: Focuses on static nested vs inner classes, outer class instance references, enclosing references, and memory leaks.
Java allows classes to be defined inside other classes, known as Nested Classes. They are divided into two main categories: Static Nested Classes and non-static Inner Classes.
Core Idea
Static nested classes behave like top-level classes. Non-static inner classes hold an implicit reference to an outer object instance.
Why It Matters
Implicit references in inner classes can cause memory leaks if the inner class instance outlives the outer class instance.
Interview Lens
Evaluates instantiation syntax (e.g. new Outer().new Inner()), reference leaks, and access privileges.
Static Nested vs. Non-Static Inner Classes
- Static Nested Class (declared with
static): Behaves like a top-level class packaged inside another class. It cannot access non-static fields or methods of the outer class directly. It is instantiated using:Outer.Nested n = new Outer.Nested();. - Non-static Inner Class (declared without
static): Binds to a specific outer class instance. It can access all members (including private fields/methods) of the outer class directly. It holds an implicit reference to the outer instance (enablingOuter.thisaccess). It is instantiated using:Outer.Inner i = new Outer().new Inner();.
Memory Leak Vulnerabilities
Because non-static inner class instances hold an implicit reference to their enclosing outer class instance:
If an inner class instance is referenced by a long-lived component (e.g., a static thread pool or static queue), the outer class instance cannot be garbage collected, even if it is no longer used elsewhere. This is a common source of memory leaks in UI frameworks and callback handlers.
To prevent these leaks, declare nested classes as static if they do not need to access instance fields of the outer class.
Common Pitfalls
- Enclosing Instance leaks: Unintentionally leaking outer class instances through long-lived non-static inner class references.
- Confusing instantiation syntax: Attempting to instantiate an inner class directly without an active outer instance reference (e.g., writing
new Inner()in a static context). - Attempting to define static members in inner classes: Declaring static fields or methods inside non-static inner classes (pre-Java 16 constraint).
Best Practices
- Declare nested classes as
staticby default. Convert them to non-static inner classes only if they require direct access to instance fields of the outer class. - If an inner class must outlive its outer class, use static nested classes and pass references explicitly using weak references.
- Keep nested classes small to maintain overall class readability.
Interview-Relevant Information
Q1: What is the main difference between static nested classes and non-static inner classes?
Answer: A static nested class is independent and cannot access instance members of the outer class directly. A non-static inner class holds an implicit reference to an instance of the outer class, enabling direct access to all outer instance members, but creating a risk of memory leaks.
Q2: How do you instantiate a non-static inner class outside the outer class scope?
Answer: You must first instantiate the outer class, and then invoke the new operator on the outer instance: Outer.Inner inner = new Outer().new Inner();.
Quick Checklist
Can you distinguish static nested from inner classes, prevent enclosing reference memory leaks, write correct instantiation statements, and manage access scopes? If yes, you understand nested classes.
Use Cases
Implementing the Builder pattern inside target classes using static nested classes.
Creating helper iterator collections inside custom data structures using non-static inner classes.
Common Mistakes
Attempting to instantiate non-static inner classes directly from static method contexts.
Leaking memory in background threads by holding long-lived references to inner class instances.