Anonymous inner classes & local classes
Define-and-instantiate a one-off class in an expression; close over effectively-final locals.
A class with no name
An anonymous inner class combines defining a class and creating one object of it into a single expression. It is ideal for a small, one-off implementation of an interface or abstract class — a comparator, a listener, a Runnable — where naming a whole top-level class would be noise.
The syntax is new SuperType() { ...body... }: you write new of an interface or class, immediately followed by a class body in braces. The result is an instance of an unnamed subclass/implementer.
Worked example — an anonymous Comparator and Runnable
Comparator<String> byLength = new Comparator<String>() {
public int compare(String a, String b) {
return a.length() - b.length();
}
};
Collections.sort(list, byLength);
Here new Comparator<String>() { ... } creates an object of an anonymous class that implements Comparator<String>, supplying the one method the interface requires. The same shape wraps a unit of work as a Runnable:
Runnable task = new Runnable() {
public void run() {
System.out.println("running");
}
};
new Thread(task).start();
Capturing local variables
An anonymous (or local) class can use local variables from the enclosing method, but only if they are final or *effectively final* — assigned once and never changed. The class captures the *value*; if the variable could change after capture, the snapshot and the local would disagree, so Java forbids it.
void schedule(final int rings) {
Runnable r = new Runnable() {
public void run() {
System.out.println("ring x" + rings); // captures 'rings'
}
};
r.run();
}
Local classes
If you need a *named* one-off — perhaps to instantiate it more than once or give it a constructor — declare a local class inside the method body. It behaves like an anonymous class (same local-capture rule) but has a name:
void build() {
class Counter { // local class, visible only here
int n = 0;
void tick() { n++; }
}
Counter c = new Counter();
c.tick();
}