Appearance
Lesson 07 · Nested & Inner Classes
Objectives
After this lesson you will be able to:
- Distinguish static nested, inner (non-static), local, and anonymous classes.
- Explain how each captures the enclosing instance and local variables.
- Use the right nesting for the job.
The four kinds
| Kind | Declared | Needs an outer instance? | Can access outer instance members? |
|---|---|---|---|
| Static nested | as a static member | No | Only static ones |
| Inner (non-static) | as an instance member | Yes | Yes, including private |
| Local | inside a method | (lives in that method) | Yes (effectively final locals) |
| Anonymous | inline expression | — | Yes (effectively final locals) |
Static nested vs inner
A static nested class is just a top-level class scoped inside another — no link to an outer object. An inner class holds an implicit reference to an enclosing instance, so it can read its private members.
java
class Outer {
private int x = 10;
static class Nested { int sum(int a, int b) { return a + b; } } // no Outer needed
class Inner { int readX() { return x; } } // uses Outer.this.x
}
Outer.Nested n = new Outer.Nested(); // no Outer instance
Outer.Inner i = new Outer().new Inner(); // needs an Outer instanceExam trap
Creating an inner class needs an enclosing instance: the outer.new Inner() syntax. A static nested class is built with just new Outer.Nested(). An inner (non-static) class cannot declare static members (except static final constants).
Local and anonymous classes
A local class is declared inside a method; an anonymous class is a local class with no name, declared and instantiated in one expression — typically to implement an interface on the spot.
java
Runnable r = new Runnable() { // anonymous class implementing Runnable
@Override public void run() { System.out.println("hi"); }
};
interface Greeter { String greet(); }
Greeter g = () -> "hello"; // a lambda — lighter than an anonymous classGotcha
Local and anonymous classes may only capture local variables that are final or effectively final (never reassigned). Mutating a captured local — or trying to — is a compile error. They can freely read and mutate fields of the enclosing instance.
Beyond the exam
Lambdas (Module 06) replace most anonymous classes for functional interfaces, but anonymous classes are still needed when you must implement multiple methods or extend a class. A lambda has no this of its own — this refers to the enclosing instance, unlike an anonymous class.
Key Takeaways
- Static nested: no outer instance (
new Outer.Nested()); sees only static outer members. - Inner (non-static): bound to an enclosing instance (
outer.new Inner()), sees its private members; can't hold non-constantstaticmembers. - Local/anonymous classes capture only effectively final locals; they may mutate enclosing fields.
- An anonymous class implements/extends a type inline; a lambda is the lighter choice for a functional interface.
Lesson Quiz
How do you create an instance of a non-static inner class Inner of Outer?
Which local variables can an anonymous class capture?
A static nested class can access...
Which CANNOT an inner (non-static) class declare?
Next: Pattern Matching. Run the matching code in labs/src/main/java/com/jse21/m03_oop/.