Back to results for “Design Patterns in Java”
Java › Inner Classes & Anonymous Classes

How would you use a local class defined within a method to implement a fairly complex, stateful callback that needs multiple methods and constructor parameters, where a lambda expression genuinely wouldn't suffice?

Advanced

Answer

When a callback's implementation needs more than a single abstract method (implementing an interface with multiple methods, or needing additional helper methods beyond the interface's own requirements), needs its own dedicated constructor accepting configuration specific to that particular usage, or needs to maintain meaningful internal state across multiple method calls beyond what captured local variables alone would cleanly support, a local class provides these capabilities that a lambda expression (limited to implementing exactly one functional interface method, with no true independent constructor or multiple methods) fundamentally cannot.
public FileVisitor<Path> createVisitor(String targetExtension) {
    class ExtensionCountingVisitor implements FileVisitor<Path> {
        private int matchCount = 0;  // meaningful internal state across multiple method calls

        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            if (file.toString().endsWith(targetExtension)) { matchCount++; }
            return FileVisitResult.CONTINUE;
        }
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; }
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) { return FileVisitResult.CONTINUE; }
        public FileVisitResult visitFileFailed(Path file, IOException exc) { return FileVisitResult.CONTINUE; }
        int getMatchCount() { return matchCount; }  // extra method beyond the interface's own requirements
    }
    return new ExtensionCountingVisitor();
}
Real-world example A file-tree-walking utility implements FileVisitor<Path> (which has four required methods, ruling out a lambda entirely) as a local class maintaining a running match count across the entire traversal, additionally exposing a getMatchCount() method beyond the interface's own contract, capabilities a simple lambda expression couldn't provide.

Common follow-ups: At what point does a local class's complexity suggest it should instead become a proper named top-level or nested class for better readability/reusability?;How would you achieve similar stateful behavior using only lambdas and an external mutable container instead of a local class?