Java Inner Classes
Inner classes in Java are classes defined inside another class.
They are useful for logically grouping classes, hiding implementation details, and creating classes that are tightly coupled with their outer class.
Types of Inner Classes
Java provides four main types:
- Regular Inner Class
- Static Nested Class
- Local Inner Class
- Anonymous Inner Class
Let’s understand each one and when they are useful.
1. Regular (Non-Static) Inner Class
A non-static inner class is tied to an instance of the outer class.
Characteristics:
- Can access ALL members of the outer class (including private fields)
- Requires an instance of the outer class to be created
- Has an implicit reference to the outer class: OuterClass.this
Example:
class Outer {
private int x = 10;
class Inner {
void show() {
System.out.println(x); // allowed
}
}
}
2. Static Nested Class
A static nested class behaves like a normal top-level class but nested inside another class.
Characteristics:
- Does NOT require an instance of the outer class
- Cannot access non-static fields/methods of the outer class
- More memory-efficient because it does NOT hold a hidden reference to Outer.this
- Often used for helper classes or builders
class Outer {
static class Nested {
void show() {
System.out.println("Inside static nested class");
}
}
}
Why Should Some Inner Classes Be Static?
1. To Avoid Hidden Outer Class Reference
A non-static inner class automatically stores a reference to its outer instance.
This causes:
- More memory usage
- Potential memory leaks
- More complex construction
Use static when the inner class does not need outer fields.
2. Better Performance
Static nested classes:
- Load faster
- Don’t require OuterClass object
- Have no pointer to the outer instance
This improves performance in high-load systems.
3. Cleaner Architecture
If the inner class is a helper or utility:
- Builders
- DTOs
- Cache entries
- Comparators
it should be static because it doesn’t conceptually belong to an instance.
4. Required by Java API Design
Common in Map.Entry, Thread.State, Comparators inside collections.
Example:
public class Outer {
public static class Entry { }
}
This is recommended practice for nested structures.
When NOT to Make It Static?
Use a non-static inner class if:
- It logically depends on outer instance state
- It needs to modify or access outer class fields
- It is a tightly coupled behaviour (e.g., Iterator for a custom list)
Example:
class GenericList<T> {
private T[] items;
private int count;
class ListIterator {
boolean hasNext() { }
T next() { }
}
}
Iterator must be non-static, because it depends on list data.
Summary Table
| Type | Needs Outer Instance? | Access Outer Fields | Common Usage |
|---|---|---|---|
| Inner Class | Yes | Yes (all) | Iterators, behavior tied to object |
| Static Nested Class | No | Only static | Builders, helpers, DTOs |
| Local Class | Yes | Yes | Methods, callback logic |
| Anonymous Class | Yes | Yes | One-time small logic |
Final Notes
- Make inner classes static whenever possible.
- Use non-static inner classes only when you need access to outer instance fields.
- Static nested classes reduce memory overhead and improve performance.
- This is also the recommended design by Effective Java (Joshua Bloch).