Topic 116 of 119 14. Additional Java Topics Interactive Tutorial

Java Nested and Inner Classes: Static Nested, Member, Local, and Anonymous Classes

10 mins read Last updated: 22 Aug 2026 17,068 views

Direct Answer & Core Concept

Java allows a class to be declared inside another class. Such a class is called a nested class.

Nested classes are useful when one class is strongly related to another class and should not be exposed as a separate top-level type. They can improve encapsulation, keep related code together, and make certain implementation details easier to organize.

Java provides four commonly discussed forms:

  1. Static nested class

  2. Member inner class

  3. Local class

  4. Anonymous class

Although all four are declared inside another class or method context, their behavior and use cases are different.

Detailed Explanation & Mechanics

What Is a Nested Class in Java?

A nested class is a class declared inside another class or interface.

For example:

Main.java
Run Online
class Outer {
    class Inner {
        void show() {
            System.out.println("Inside Inner");
        }
    }
}

Here:

Architecture Diagram
Outer
 └── Inner

Inner is nested inside Outer.

Nested classes can access members of their enclosing class according to the applicable access rules.


Why Use Nested Classes?

Nested classes are useful when a helper type is meaningful only in the context of its enclosing class.

For example, suppose a Car class needs an internal Engine class:

Main.java
Run Online
class Car {
    class Engine {
        void start() {
            System.out.println("Engine started");
        }
    }
}

If Engine is only useful as part of Car, keeping it inside Car can make the relationship clear.

Common reasons to use nested classes include:

  • Encapsulation

  • Keeping related code together

  • Hiding implementation details

  • Creating helper classes

  • Implementing callbacks

  • Building specialized data structures

  • Organizing code around a containing class


Four Types of Nested Classes

Java commonly distinguishes four forms:

TypeDeclared Where?Static?Has Enclosing Instance?
Static nested classClass bodyYesNo
Member inner classClass bodyNoYes
Local classMethod/block/constructorNoYes, when applicable
Anonymous classExpressionNoYes, when applicable

The biggest distinction is whether the nested class requires an instance of the enclosing class.


Static Nested Class

A static nested class is declared with the static keyword inside another class.

Example:

Main.java
Run Online
class Outer {
    static class Nested {
        void show() {
            System.out.println("Static nested class");
        }
    }
}

The nested class belongs to the enclosing class rather than to a particular instance of the enclosing class.


Creating a Static Nested Class Object

You do not need an Outer object to create a static nested class.

Use:

Main.java
Run Online
Outer.Nested object = new Outer.Nested();
object.show();

Complete example:

Main.java
Run Online
class Outer {
    static class Nested {
        void display() {
            System.out.println("Hello from nested class");
        }
    } public static void main(String[] args) {
        Outer.Nested nested = new Outer.Nested();
        nested.display();
    }
}

Output:

Notice the syntax:

rather than:


Static Nested Class and Outer Instance

A static nested class does not automatically have a reference to an enclosing Outer object.

For example:

Main.java
Run Online
class Outer {
    int value = 100;
    static class Nested {
        void show() {
            // System.out.println(value); // Error
        }
    }
}

The static nested class cannot directly access the instance field value.

It can access static members of the enclosing class directly:

Main.java
Run Online
class Outer {
    static int value = 100;
    static class Nested {
        void show() {
            System.out.println(value);
        }
    }
}

Output:


Static Nested Class Accessing Outer Instance

A static nested class can still work with an Outer object if you explicitly provide one.

Main.java
Run Online
class Outer {
    int value = 100;
    static class Nested {
        void show(Outer outer) {
            System.out.println(outer.value);
        }
    }
}

Usage:

Main.java
Run Online
Outer outer = new Outer();
Outer.Nested nested = new Outer.Nested();
nested.show(outer);

The important point is that the enclosing instance must be supplied explicitly.


Member Inner Class

A member inner class is a non-static class declared directly inside another class.

Example:

Main.java
Run Online
class Outer {
    int value = 100;
    class Inner {
        void show() {
            System.out.println(value);
        }
    }
}

Unlike a static nested class, a member inner class is associated with an instance of the enclosing class.


Creating a Member Inner Class

You first create an Outer object:

Main.java
Run Online
Outer outer = new Outer();

Then create the inner object:

Main.java
Run Online
Outer.Inner inner = outer.new Inner();

Complete example:

Main.java
Run Online
class Outer {
    int value = 100;
    class Inner {
        void show() {
            System.out.println("Value = " + value);
        }
    } public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.show();
    }
}

Output:


Why Does Inner Class Use outer.new?

The syntax:

makes the relationship explicit.

The Inner object is associated with the particular Outer object represented by:

Therefore two different Outer objects can have different inner-class objects associated with them.


Member Inner Class Accessing Outer Members

An inner class can access members of its enclosing class.

Main.java
Run Online
class Person {
    private String name = "Tanmoy";
    class Profile {
        void display() {
            System.out.println(name);
        }
    }
}

The inner class can access the private field:

because it is nested within the same top-level class context.


Outer Class Accessing Inner Members

The enclosing class can also access members of the inner class when it has an instance of that inner class.

Main.java
Run Online
class Outer {
    class Inner {
        private int value = 50;
    } void show() {
        Inner inner = new Inner();
        System.out.println(inner.value);
    }
}

The enclosing class and nested class have access relationships that allow them to work closely together.


Static Members Inside Inner Classes

A non-static inner class cannot freely declare arbitrary static members in all Java versions and contexts.

Modern Java permits certain static declarations in inner classes, including static final constant variables, and newer Java versions have expanded what can be declared.

For beginner code, the safest mental model is:

Main.java
Run Online
static nested class → designed for static contextinner class → associated with an outer instance

If a nested class does not need an enclosing object, a static nested class is often simpler.


Local Class

A local class is a named class declared inside a method, constructor, initializer, or another appropriate block.

Example:

Main.java
Run Online
class Outer {
    void display() {
        class Local {
            void show() {
                System.out.println("Inside local class");
            }
        } Local object = new Local();
        object.show();
    }
}

Here, Local exists only within the scope where it is declared.


Scope of a Local Class

Consider:

Main.java
Run Online
void display() {
    class Local {
        void show() {
            System.out.println("Hello");
        }
    } Local object = new Local();
    object.show();
}

The Local class cannot normally be referenced outside the method:

Main.java
Run Online
// Local object = ...; // Not visible here

This makes local classes useful for small helper implementations that are needed only inside one method or block.


Local Class Accessing Local Variables

A local class can access local variables from its enclosing method when those variables are final or effectively final.

Example:

Main.java
Run Online
class Example {
    void display() {
        String message = "Hello";
        class Local {
            void show() {
                System.out.println(message);
            }
        } Local object = new Local();
        object.show();
    }
}

Output:

message is effectively final because its value is not changed after initialization.


What Does Effectively Final Mean?

A variable is effectively final if it is assigned once and is not modified afterward.

This is valid:

Main.java
Run Online
String message = "Hello";
class Local {
    void show() {
        System.out.println(message);
    }
}

But this causes a problem:

Main.java
Run Online
String message = "Hello";
message = "World";
class Local {
    void show() {
        System.out.println(message);
    }
}

The local variable is no longer effectively final.


Local Class Accessing Instance Members

A local class can also access members of the enclosing object.

Main.java
Run Online
class Example {
    private int value = 100;
    void display() {
        class Local {
            void show() {
                System.out.println(value);
            }
        } new Local().show();
    }
}

Output:

This is useful when a local helper needs access to the state of its enclosing object.


Anonymous Class

An anonymous class is a class without a name that is declared and instantiated in a single expression.

Example:

Main.java
Run Online
Runnable task = new Runnable() {
    @Override public void run() {
        System.out.println("Task running");
    }
};

There is no class name such as:

Instead, the class body is created directly where the object is needed.


Anonymous Class Implementing an Interface

One common use is implementing an interface for a one-time purpose.

Main.java
Run Online
interface Greeting {
    void sayHello();
}public class Main {
    public static void main(String[] args) {
        Greeting greeting = new Greeting() {
            @Override public void sayHello() {
                System.out.println("Hello!");
            }
        };
        greeting.sayHello();
    }
}

Output:

The anonymous class provides the implementation without requiring a separate named class.


Anonymous Class Extending a Class

An anonymous class can also extend a class.

Main.java
Run Online
class Animal {
    void sound() {
        System.out.println("Animal sound");
    }
}

Create an anonymous subclass:

Main.java
Run Online
Animal animal = new Animal() {
    @Override void sound() {
        System.out.println("Dog barking");
    }
};
animal.sound();

Output:

The anonymous class overrides the method without defining a separate named subclass.


Anonymous Classes and Constructor Arguments

An anonymous class can call a constructor of the superclass or interface-related implementation context.

Example:

Main.java
Run Online
class Person {
    Person(String name) {
        System.out.println("Name: " + name);
    } void display() {
        System.out.println("Person");
    }
}

Create an anonymous subclass:

Main.java
Run Online
Person person = new Person("Tanmoy") {
    @Override void display() {
        System.out.println("Anonymous subclass");
    }
};

The constructor argument:

is passed to the superclass constructor.


Anonymous Class with an Interface

For a one-time implementation:

Main.java
Run Online
interface Calculator {
    int calculate(int a, int b);
}Calculator calculator = new Calculator() {
    @Override public int calculate(int a, int b) {
        return a + b;
    }
};
System.out.println(calculator.calculate(10, 20));

Output:

For a functional interface, however, a lambda expression is often simpler when the operation can be expressed as a lambda.

For example:

Main.java
Run Online
Calculator calculator =(a, b) -> a + b;

Anonymous Class vs Lambda

Consider this anonymous class:

Main.java
Run Online
Runnable task = new Runnable() {
    @Override public void run() {
        System.out.println("Running");
    }
};

A lambda can often replace it:

Main.java
Run Online
Runnable task =() -> {
    System.out.println("Running");
};

Or more simply:

Main.java
Run Online
Runnable task =() -> System.out.println("Running");

Lambdas are generally preferable for simple functional-interface implementations.

Anonymous classes remain useful when you need a class body with behavior or state that does not fit naturally into a lambda.


Four Types Compared

Static Nested Class

Main.java
Run Online
class Outer {
    static class Nested {
    }
}

Create it with:

Main.java
Run Online
Outer.Nested object = new Outer.Nested();

It does not require an Outer instance.


Member Inner Class

Main.java
Run Online
class Outer {
    class Inner {
    }
}

Create it with:

Main.java
Run Online
Outer outer = new Outer();
Outer.Inner object = outer.new Inner();

It is associated with an Outer instance.


Local Class

Main.java
Run Online
void method() {
    class Local {
    } Local object = new Local();
}

Its declaration is limited to the surrounding method or block.


Anonymous Class

Main.java
Run Online
Runnable task = new Runnable() {
    @Override public void run() {
        System.out.println("Running");
    }
};

It has no explicit class name and is usually created for a specific local purpose.


Nested Class Access Comparison

FeatureStatic NestedMember InnerLocalAnonymous
Has explicit class nameYesYesYesNo
Declared in class bodyYesYesNoNo
Uses staticYesNoNoNo
Requires outer instanceNoYesDepends on contextDepends on context
Typical scopeClassClassLocal block/methodSingle expression
Common useHelper/data typeObject-specific helperMethod-specific helperOne-off implementation

Accessing Outer Class with Outer.this

A member inner class can explicitly refer to its enclosing object using:

Example:

Main.java
Run Online
class Outer {
    int value = 100;
    class Inner {
        int value = 200;
        void show() {
            System.out.println(value);
            System.out.println(this.value);
            System.out.println(Outer.this.value);
        }
    }
}

Output:

Here:

refers to the inner class's field.

While:

refers to the enclosing Outer object's field.


this in Nested Classes

Each non-static nested object has its own this reference.

For an inner class:

Main.java
Run Online
class Outer {
    class Inner {
        void show() {
            System.out.println(this);
        }
    }
}

this refers to the current Inner object.

It does not refer directly to the Outer object.

To access the outer instance:

is used.


Static Nested Classes and this

A static nested class has its own this reference when an instance of the nested class exists:

Main.java
Run Online
class Outer {
    static class Nested {
        void show() {
            System.out.println(this);
        }
    }
}

But it does not have:

because it is not associated with an enclosing Outer instance.


Nested Classes and Encapsulation

Nested classes can improve encapsulation by keeping implementation-specific types close to the code that uses them.

For example:

Main.java
Run Online
class LinkedStructure {
    private class Node {
        int value;
        Node next;
        Node(int value) {
            this.value = value;
        }
    }
}

The Node class is an implementation detail of LinkedStructure.

External code does not need to know how nodes are represented internally.


Static Nested Class for a Helper Type

Suppose a class needs a helper object that does not depend on an enclosing object:

Main.java
Run Online
class Report {
    static class Summary {
        int total;
        int errors;
        Summary(int total, int errors) {
            this.total = total;
            this.errors = errors;
        }
    }
}

The helper can be used as:

Main.java
Run Online
Report.Summary summary = new Report.Summary(100, 5);

A static nested class is appropriate because Summary does not need a particular Report instance.


Member Inner Class for Object-Specific Behavior

Suppose each bank account has an object representing its transaction helper:

Main.java
Run Online
class BankAccount {
    private double balance;
    class Transaction {
        void deposit(double amount) {
            balance += amount;
        }
    }
}

The inner class can directly access the enclosing object's state.

Usage:

Main.java
Run Online
BankAccount account = new BankAccount();
BankAccount.Transaction transaction = account.new Transaction();

This is useful when the helper is naturally tied to a particular outer object.


Local Class for Temporary Logic

A local class can be useful when a helper is too substantial for a lambda but is needed only inside one method.

Main.java
Run Online
void process() {
    class Formatter {
        String format(String text) {
            return "[" + text + "]";
        }
    } Formatter formatter = new Formatter();
    System.out.println(formatter.format("Java"));
}

The Formatter class does not need to be visible outside process().


Anonymous Class for One-Time Behavior

Anonymous classes are useful when you need a small one-off implementation.

Main.java
Run Online
Thread thread = new Thread(new Runnable() {
    @Override public void run() {
        System.out.println("Background task");
    }
});
thread.start();

Modern Java often uses a lambda here:

Main.java
Run Online
Thread thread = new Thread(() -> System.out.println("Background task"));
thread.start();

But the anonymous-class form is still important for understanding older Java APIs and existing codebases.


Advantages of Nested Classes

Nested classes provide several useful benefits.

Better Encapsulation

Implementation details can remain inside the class that owns them.

Logical Grouping

Related types can be placed together instead of scattered across multiple files.

Access to Enclosing Members

Inner classes can work directly with members of their enclosing object.

Reduced Namespace Pollution

Small helper types do not necessarily need to become publicly visible top-level classes.

Localized Implementations

Local and anonymous classes allow behavior to be defined close to where it is used.


Disadvantages and Things to Consider

Nested classes are not automatically better than top-level classes.

Too many nested classes can make code difficult to read.

Member inner classes also maintain a relationship with an enclosing instance, which can matter for object lifetime and memory usage.

Anonymous classes can become difficult to understand when their implementation grows large.

If a class has substantial independent responsibilities, a separate top-level class may be clearer.


Best Practices

Prefer Static Nested Classes When No Outer Instance Is Needed

If the nested class does not use instance state from the enclosing class, consider:

rather than a member inner class.

Use Member Inner Classes for Strong Object Relationships

Use a non-static inner class when the nested object genuinely belongs to a particular enclosing instance.

Keep Local Classes Small

A local class should generally solve a focused problem within its surrounding method or block.

Prefer Lambdas for Simple Functional Interfaces

For interfaces with one abstract method, a lambda is often shorter and clearer.

Avoid Huge Anonymous Classes

If an anonymous class becomes large, give it a meaningful name and consider moving it to a separate class.

Use Nested Classes for Logical Encapsulation

A nested class is most useful when its relationship with the enclosing class is meaningful rather than merely convenient.


Common Mistakes

Mistake 1: Creating an Inner Class Like a Static Nested Class

This is incorrect for a member inner class:

Main.java
Run Online
Outer.Inner object = new Outer.Inner();

Instead:

Main.java
Run Online
Outer outer = new Outer();
Outer.Inner object = outer.new Inner();

Mistake 2: Assuming Static Nested Classes Have Outer Instances

A static nested class does not automatically have:

It is not tied to an enclosing Outer object.


Mistake 3: Modifying a Captured Local Variable

This does not work:

Main.java
Run Online
int count = 10;
class Local {
    void show() {
        System.out.println(count);
    }
}count++;

A local variable captured by a local or anonymous class must be final or effectively final.


Mistake 4: Using an Anonymous Class for Everything

Anonymous classes are useful for one-off behavior, but a named class is usually clearer when the implementation becomes large or reusable.


Complete Example of All Four Types

Main.java
Run Online
public class Outer {
    private int outerValue = 100;
    //
    1. Static nested class static class StaticNested {
        void show() {
            System.out.println("Static nested class");
        }
    } //
    2. Member inner class class MemberInner {
        void show() {
            System.out.println("Member inner class");
            System.out.println("Outer value = " + outerValue);
        }
    } void demonstrate() {
        //
        3. Local class class LocalClass {
            void show() {
                System.out.println("Local class");
            }
        } LocalClass local = new LocalClass();
        local.show();
        //
        4. Anonymous class Runnable task = new Runnable() {
            @Override public void run() {
                System.out.println("Anonymous class");
            }
        };
        task.run();
    } public static void main(String[] args) {
        // Static nested class
        Outer.StaticNested nested = new Outer.StaticNested();
        nested.show();
        // Member inner class
        Outer outer = new Outer();
        Outer.MemberInner inner = outer.new MemberInner();
        inner.show();
        // Local and anonymous classes
        outer.demonstrate();
    }
}

Output:

Main.java
Run Online
Static nested classMember inner classOuter value = 100Local classAnonymous class

This example demonstrates the structural difference between all four forms.


Frequently Asked Questions

What is a nested class in Java?

A nested class is a class declared inside another class or interface. Java supports static nested classes and several forms of non-static nested classes.

What is an inner class?

In common Java terminology, an inner class is a non-static nested class. Member inner classes, local classes, and anonymous classes are non-static nested classes.

What is a static nested class?

A static nested class is declared with static inside another class. It does not require an instance of the enclosing class.

Main.java
Run Online
Outer.Nested object = new Outer.Nested();

What is a member inner class?

A member inner class is a non-static class declared directly inside another class.

Main.java
Run Online
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();

It is associated with the enclosing instance.

What is a local class?

A local class is declared inside a method, constructor, initializer, or block. Its scope is limited to that surrounding context.

What is an anonymous class?

An anonymous class has no explicit name and is declared and instantiated in one expression.

Main.java
Run Online
Runnable task = new Runnable() {
    public void run() {
        System.out.println("Running");
    }
};

Can an inner class access private members of the outer class?

Yes. A nested class can access members of its enclosing class according to Java's access rules, including private members.

Can a static nested class access instance variables of the outer class?

Not directly. It does not have an enclosing instance. You must provide an Outer object explicitly if the nested class needs to access instance state.

What is Outer.this?

Outer.this refers to the current enclosing instance from a member inner class.

Main.java
Run Online
System.out.println(Outer.this.value);

Can a local class access local variables?

Yes, but local variables captured by the local class must be final or effectively final.

Are anonymous classes still used in modern Java?

Yes, although lambdas are often preferable for simple functional interfaces. Anonymous classes remain useful for more complex one-off implementations and existing APIs.

Which nested class should I use?

Use a static nested class when no enclosing instance is needed, a member inner class when the nested object belongs to an enclosing instance, a local class for method-scoped helper behavior, and an anonymous class for a one-off implementation.

Graphics and Design Ideas

Graphic 1 — Four Types of Nested Classes

Architecture Diagram
                 JAVA NESTED CLASSES
                         │
        ┌────────────────┼────────────────┐
↓

↓

↓
Static Nested      Member Inner       Local
        │                │                │
  No outer object    Outer instance    Method scope
        │                │                │
        └────────────────┴───────┐        │
↓

↓
Anonymous Class
                              One-off use

Graphic 2 — Object Creation Comparison

Main.java
Run Online
STATIC NESTEDOuter.Nested n = new Outer.Nested();
MEMBER INNEROuter outer = new Outer();
Outer.Inner i = outer.new Inner();

This visual makes one of the most confusing beginner concepts immediately clear.

Graphic 3 — Scope Visualization

Architecture Diagram
Outer Class
│
├── Static Nested Class
│
├── Member Inner Class
│
└── method()
      │
      ├── Local Class
      │
      └── Anonymous Class

Graphic 4 — Outer Instance Relationship

Architecture Diagram
Static Nested
     │
     X
     │
Outer Object


Member Inner
     │
     │ associated with
↓
Outer Object

Use a visual distinction between "has no automatic outer instance" and "associated with outer instance."

Graphic 5 — Anonymous Class vs Lambda

Main.java
Run Online
Anonymous ClassRunnable task = new Runnable() {
    public void run() {
        work();
    }
};
LambdaRunnable task =() -> work();

This is useful for showing how modern Java can replace many simple anonymous-class implementations with more concise lambda expressions.

Runnable Code Example: Java Nested and Inner Classes

Java 17+
Main.java
Run Online
public class NestedClassDemo {
    private static String staticMsg = "Static Context";
    private String instanceMsg = "Instance Context";
    //
    1. Static Nested Class public static class StaticNested {
        public void print() {
            System.out.println("Nested: " + staticMsg);
        }
    } //
    2. Inner Member Class public class InnerMember {
        public void print() {
            System.out.println("Inner: " + instanceMsg);
        }
    } public static void main(String[] args) {
        StaticNested nested = new StaticNested();
        nested.print();
        NestedClassDemo outer = new NestedClassDemo();
        InnerMember inner = outer.new InnerMember();
        inner.print();
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

Why is a static nested class preferred over a non-static inner class when outer instance access is not needed?

Static nested classes do not retain an implicit reference to the enclosing class, reducing memory footprint and avoiding memory leaks.
Q2

What variables can an anonymous class access from its enclosing method?

Only final or effectively final local variables.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Make nested classes static by default unless direct access to enclosing instance fields is explicitly required.