W3docs

Java Local Classes

Declare classes inside method bodies in Java with local inner classes, with access to effectively-final locals.

A local class is a class declared inside a method body (or a constructor, or an initializer block). It's scoped to the block it's declared in — nothing outside that block can mention it by name. Otherwise it acts much like an inner class, with access to the enclosing instance's members and to the method's effectively-final locals.

Local classes are rare in modern Java. Lambdas have replaced their main use cases for one-method callbacks, and anonymous classes are usually shorter for one-off implementations. But a local class is occasionally the cleanest option when you need a named type that participates in the enclosing method's logic and isn't useful anywhere else.

Declaring one

A class declaration sitting inside a method body:

public void process(List<String> lines) {
  class Counter {
    int n = 0;
    void inc() { n++; }
  }

  Counter c = new Counter();
  for (String s : lines) if (!s.isBlank()) c.inc();

  System.out.println("non-blank lines: " + c.n);
}

Outside process, nobody can see Counter — its name doesn't exist beyond the method's closing brace. Inside, you use it like any other class.

Why pick it over an anonymous class?

A local class has a real name, which buys you a few things an anonymous class can't have:

  • A constructor. You can give it parameters, write validation, and have multiple constructors.
  • Multiple instances. Since the class has a name, you can write new Counter() more than once. An anonymous class definition only creates one instance per expression.
  • Self-reference. Counter can take itself as a parameter, hold a Counter next field, recurse — all the things named types can do.
  • Readability. A name like Counter documents what the helper is for. Anonymous new Object() { ... } blocks are harder to skim.

Access to enclosing state

Local classes can:

  • Read and write fields of the enclosing instance (if the enclosing method is non-static).
  • Call instance methods of the enclosing class.
  • Read — but not reassign — the enclosing method's final or effectively final local variables and parameters.
void run(int multiplier) {
  class Scaler {
    int scale(int x) { return x * multiplier; }   // captures the parameter
  }
  System.out.println(new Scaler().scale(7));
}

multiplier is captured into the synthetic class as a field. The "effectively final" requirement is the reason — if multiplier could be reassigned inside run after Scaler had captured its old value, the two would silently disagree.

In a static method

In a static method, the local class is implicitly static — it has no enclosing instance to refer to:

public static int demo() {
  class Helper {
    int square(int n) { return n * n; }
  }
  return new Helper().square(7);
}

There's no Outer.this here, because the enclosing method is static. Helper can still capture effectively-final locals from demo, just not instance fields of an enclosing object that doesn't exist.

When to actually use one

Concrete cases where a local class genuinely beats the alternatives:

  • The helper has more than one method, and you'd rather see the methods grouped together with a clear name than spread across anonymous-class boilerplate.
  • The helper needs a constructor to validate its setup.
  • The helper recurses or holds references to other instances of its own type.

If a lambda or short anonymous class would do, prefer that. Local classes are a niche tool.

Modifiers

A local class can be declared final (preventing subclasses, though it has no name to extend anyway), abstract (rare — you'd need a local subclass too), or with no access modifier (access modifiers on local classes are not allowed — there's no place outside the block they could be visible from).

A worked example

java— editable, runs on the server

What's next

That wraps up the nested-class tour — and most of Java's classical OOP machinery. The next section of Part 6 moves into the special class kinds: types Java provides for specific shapes of data, starting with enum for fixed sets of constants. Continue to Java enums.

Practice

Practice

Why might you choose a local class over an anonymous class for the same job?