⚡IntermediateAdvanced OOP

Nested and Inner Classes

Define classes inside other classes: static nested classes, inner classes, local classes, and anonymous classes.

Overview

Java lets you define a class inside another class. There are four kinds: 1. Static nested class: declared with static. It has no access to the outer instance. 2. Inner class (non-static nested class): has access to all members of the outer class, including private ones. 3. Local class: defined inside a method. 4. Anonymous class: an inline, one-time class definition with no name. Nested classes are used to logically group classes that belong together and to increase encapsulation.

Key Points

  • •A static nested class is like a top-level class but scoped inside another class
  • •An inner class holds a reference to the outer class instance. Instantiate with: outer.new Inner()
  • •Inner classes can access private members of the outer class
  • •Local classes are defined and used inside a single method
  • •Anonymous classes implement an interface or extend a class inline with no class name
  • •Anonymous classes are useful for one-off implementations (event handlers, comparators)
  • •With lambdas and method references (Java 8+), anonymous classes for functional interfaces are often replaced by lambdas

Examples

Static nested class

public class Main {
    static class Builder {
        private String name = "";
        private int age = 0;

        Builder name(String name) { this.name = name; return this; }
        Builder age(int age) { this.age = age; return this; }
        String build() { return name + " (age " + age + ")"; }
    }

    public static void main(String[] args) {
        // Access static nested class without an outer instance
        Builder b = new Builder();
        String person = b.name("Alice").age(30).build();
        System.out.println(person); // Alice (age 30)
    }
}

Static nested classes are accessed as OuterClass.NestedClass but here Builder is inside Main so it is just Builder. Use static nested classes when the class does not need access to the outer instance.

Inner class accessing outer members

public class Main {
    private String secret = "top-secret";

    class Insider {
        void reveal() {
            // Accesses outer instance's private field
            System.out.println("The secret is: " + secret);
        }
    }

    public static void main(String[] args) {
        Main outer = new Main();
        Main.Insider inner = outer.new Insider();
        inner.reveal(); // The secret is: top-secret
    }
}

An inner class instance is always tied to an outer class instance. You must create the outer first, then call outer.new Inner(). Inner classes can access all outer fields and methods.

Anonymous class implementing an interface

import java.util.Arrays;
import java.util.List;

public class Main {
    interface Greeter {
        String greet(String name);
    }

    public static void main(String[] args) {
        // Anonymous class implementing Greeter
        Greeter formal = new Greeter() {
            @Override
            public String greet(String name) {
                return "Good day, " + name + ".";
            }
        };

        Greeter casual = new Greeter() {
            @Override
            public String greet(String name) {
                return "Hey " + name + "!";
            }
        };

        System.out.println(formal.greet("Alice")); // Good day, Alice.
        System.out.println(casual.greet("Bob"));   // Hey Bob!

        // Sorting with an anonymous Comparator
        List<String> words = Arrays.asList("banana", "apple", "cherry");
        words.sort(new java.util.Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return a.length() - b.length(); // sort by length
            }
        });
        System.out.println(words); // [apple, banana, cherry]
    }
}

Anonymous classes implement an interface or extend a class at the point of use. Since Greeter is a functional interface, it could also be written as a lambda: name -> "Hey " + name + "!".

Common Mistakes

  • Creating an inner class instance without an outer instance. You need outer.new Inner(), not new Inner()
  • Making an inner class static when it needs to access outer fields, or non-static when it does not. If the inner class does not need the outer instance, make it static to avoid memory leaks
  • Using anonymous classes for functional interfaces when a lambda is shorter and more readable

Note

Prefer lambdas over anonymous classes when implementing a functional interface. Reserve anonymous classes for cases where you need to override multiple methods or add fields/state to the anonymous object.

Exercises

Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.

Loading editor…

Completed: 0 / 4 exercises

Knowledge Check

Question 1 of 4

What is the key difference between a static nested class and an inner class?