skip to content

Inner (Non-static) Classes

Non-static inner classes carry an implicit reference to their enclosing instance, which is why they can read outer fields, need Outer.this to disambiguate, and must be created from an outer instance. That hidden reference is the leak interviewers want you to name.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What is an inner (non-static) class in Java, and how does it differ from a static nested class?

level: juniorimportance: must knowfreq 72%

answer

  1. non-static = bound to an outer instance
  2. implicit hidden reference to outer
  3. can touch outer's private members
  4. static nested = no outer link, stands alone
  5. default to static; go inner only when state is needed

basics

~20 s

An inner class is a non-static class defined inside another class. Each inner-class object is tied to an object of the outer class and can use the outer object's fields and methods. A static nested class has no such tie.

solid answer

~40 s

An inner (non-static) class is a member class declared without the `static` keyword inside another class. Every inner-class instance is bound to a specific instance of the enclosing (outer) class, so it implicitly holds a reference to that outer object. Because of this binding, inner-class code can directly read and modify the outer instance's fields and call its methods, even private ones. You cannot create an inner-class instance without first having an outer instance. A static nested class, by contrast, carries no outer reference: it behaves like a top-level class that happens to live inside another for namespacing, and it can only touch the outer class's static members. Choose an inner class when the helper genuinely needs the outer object's state; otherwise prefer a static nested class.

go deeper

for a junior

Knows an inner class is non-static, lives inside another class, and can use the outer object's fields.

for a middle

Can clearly contrast inner vs static nested: the implicit outer reference, construction differences, and when to use each.

for a senior

Articulates the memory/leak consequence of the hidden outer reference and cites the default-to-static guidance with rationale.

for a principal

Frames the choice as an API/lifetime design decision (escaping references, GC retention, serialization pitfalls) and can reason about it across a codebase.

## Terms first - **Class**: a blueprint for objects. An **object** (or **instance**) is a concrete value created from a class with `new`. - **Nested class**: any class declared *inside* another class. Java has two broad kinds: **static nested classes** (declared `static`) and **inner classes** (declared *without* `static`). This question is about the non-static kind. - **Outer / enclosing class**: the class that physically contains the nested class. The nested class is sometimes called the **member class**. ## What makes an inner class special An **inner class** is a member class written without `static`. The defining rule: **every inner-class object belongs to one outer-class object.** When you create an inner-class instance, the runtime stores a hidden reference to a specific outer instance inside it. That hidden link is why inner-class code may freely use the outer object's members — including `private` ones — as if they were its own. A **static nested class** has no such hidden link. It is essentially a normal top-level class that the author chose to file *inside* another class for organization. It can only reach the outer class's `static` members, never per-instance fields, because it is not attached to any outer instance. ## Why the distinction matters 1. **Construction.** You can build a static nested class with `new Outer.Nested()`. You cannot build an inner class without an outer instance: `outerRef.new Inner()` (more on this syntax in a related question). 2. **Memory / lifetime.** Because an inner-class object pins the outer object alive (the hidden reference keeps it reachable for garbage collection), a long-lived inner instance can unintentionally keep a big outer object in memory — a classic leak. A static nested class has no such effect. 3. **State access.** Inner = needs the outer instance's data. Static nested = stands alone. ## A concrete mental model Think of `Map.Entry` versus an `Iterator` returned by a collection. An `Iterator` typically *is* an inner class: it must walk the very list instance that produced it, so it holds that list. A simple data-holder that does not depend on any particular outer object is a good static nested class. ## Rule of thumb Make a nested class `static` by default. Drop `static` (making it an inner class) **only** when it truly needs to read or mutate the enclosing instance's state. Effective Java explicitly recommends this, because a needless outer reference wastes memory and risks leaks.

  • Why does Effective Java recommend making a nested class static by default?
    A non-static inner class holds an implicit reference to its enclosing instance, costing memory and risking a leak that keeps the outer object alive. If the nested class does not need the outer instance, `static` avoids that reference entirely.
  • Can a static nested class access a private instance field of the outer class?
    No. It has no outer instance to read it from. It can only access the outer class's static members (and the instance members of an outer object explicitly passed to it).

An inner-class object is like a room that only exists as part of a specific house: it always knows which house it belongs to and can open that house's private cupboards. A static nested class is a portable shed — filed under the house's name, but it works fine on its own.

saying these in an interview costs you the question

  • Saying inner classes and static nested classes are the same thing
  • Claiming an inner class can be instantiated with plain `new Inner()` from outside the outer class
  • Thinking a static nested class can read per-instance outer fields

context

open as a page

How do you instantiate an inner (non-static) class from outside its enclosing class? Explain the outer.new Inner() syntax.

level: middleimportance: should knowfreq 55%

basics

~20 s

You first need an outer-class object, then create the inner object from it: Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();. You can't write new Outer.Inner() because every inner instance needs an enclosing instance.

open as a page

How do you refer to the enclosing instance from inside an inner class, including when names collide? Explain OuterClass.this.

level: middleimportance: should knowfreq 58%

basics

~20 s

Inside an inner class, plain field names refer to the inner object first. To reach the outer object explicitly — for example when both have a field with the same name — write OuterClass.this.field or OuterClass.this.method().

open as a page

Why can a non-static inner class cause a memory leak, and how do you avoid it?

level: seniorimportance: should knowfreq 47%

basics

~20 s

An inner-class object secretly holds a reference to its outer object. If the inner object lives a long time (e.g., a listener or callback), it keeps the whole outer object alive in memory even after you're done with it. Use a static nested class to break that link.

open as a page

At the bytecode level, how does the JVM implement an inner class's access to the enclosing instance and its private members?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

The compiler turns an inner class into a separate top-level class file with a hidden field (often named this$0) holding the outer object. To let it read the outer's private members, older Java generated tiny synthetic accessor methods; modern Java (11+) uses nestmates so no extra methods are needed.

open as a page