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.
Countercan take itself as a parameter, hold aCounter nextfield, recurse — all the things named types can do. - Readability. A name like
Counterdocuments what the helper is for. Anonymousnew 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
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
Why might you choose a local class over an anonymous class for the same job?