Member Inner Class in Java

Naveen AnamaneniUpdated · 5 min read

A member inner class is a class declared directly inside another class's body, without static. Every object of it is bound to one object of the outer class, the way a dashboard is bound to one car. Through that bond it can read and change the outer object's fields, even private ones, as if they were its own. That makes inner classes ideal for "views" of an outer object, such as an iterator over a custom collection.

A Playlist and Its Iterator

Playlist.java▶ Try it
import java.util.Iterator;
import java.util.NoSuchElementException;
 
public class Playlist implements Iterable<String> {
    private final String owner;
    private final String[] songs;
 
    Playlist(String owner, String... songs) {
        this.owner = owner;
        this.songs = songs;
    }
 
    public Iterator<String> iterator() {
        return new SongIterator();
    }
 
    private class SongIterator implements Iterator<String> {
        private int next = 0;
 
        public boolean hasNext() { return next < songs.length; }
 
        public String next() {
            if (!hasNext()) throw new NoSuchElementException();
            return (next + 1) + ". " + songs[next++]
                + " (" + Playlist.this.owner + ")";
        }
    }
 
    public static void main(String[] args) {
        Playlist list = new Playlist("Advitha", "Morning Raga", "Monsoon Walk");
        for (String s : list) {
            System.out.println(s);
        }
    }
}
Output
1. Morning Raga (Advitha)
2. Monsoon Walk (Advitha)

How it works

  1. SongIterator is a private member inner class: no other class can see it.
  2. It reads songs, a private field of Playlist, directly. Each iterator has its own next position.
  3. Playlist.this.owner names the outer object explicitly. Plain owner would also work here; the qualified form is needed when the inner class has its own field with the same name.
  4. iterator() is an instance method, so new SongIterator() automatically ties the new iterator to this playlist. The for-each loop calls iterator() behind the scenes.

Creating One from Outside

Inside the outer class's instance methods, new Inner() uses this as the outer object. Anywhere else, you must say which outer object:

Outside the outer class
Car car = new Car("Navika", new Car.Engine(1197));
Car.Dashboard dash = car.new Dashboard();   // the dashboard for this car

From a static method such as main, plain new Inner() fails, because there's no this:

Compiler output
NoOuter.java:4: error: non-static variable this cannot be referenced from a static context
        Inner i = new Inner();
                  ^
1 error

The Hidden Reference

An inner object keeps its outer object alive

The compiler gives every inner object a hidden field, this$0, pointing to its outer object. Two consequences follow:

  1. Every inner object is slightly bigger than a static nested one.
  2. As long as an inner object is reachable, its outer object is too. A long-lived listener or task created as an inner class of a big screen or service can keep that whole object in memory, which is a classic memory leak.

Rules

RuleDetail
Access to outer membersAll of them, including private
Outer's access to inner membersAlso all, including private
Static members inside an inner classAllowed since Java 16
Access modifiers on the inner classAny: private hides it completely
Same-named fieldsUse Outer.this.field for the outer one

Common Mistakes

Calling new Inner() from a static method. Create an outer object first: outer.new Inner().

Keeping inner objects longer than their outer object should live. They pin the outer object in memory.

Using an inner class where a static nested class would do. It adds an unused reference and blocks garbage collection.

Practice

  1. Easy: Add a member inner class Summary to Playlist with a method that returns the owner's name and the number of songs.
  2. Harder: Write a Classroom class with a private String[] students and a member inner class that iterates over the students in reverse order.

Quick check: Member inner class

4 questions
1Can a member inner class read the outer class's private fields?
2How do you refer to the outer object inside the inner class?
3Why can an inner object cause a memory leak?
4From main, how do you create a Dashboard for car?

Key Takeaways

Was this tutorial helpful?

Lesson 169 of 482