Anonymous Inner Class in Java
Sometimes you need a class for exactly one use: a special discount for one sale, or a sort order for one list. Writing a named class in its own place for that feels like too much ceremony. An anonymous class declares the class and creates its single object in one expression, right where it's needed. It has no name, so it can't be reused, and that's the point.
Two Anonymous Classes
import java.util.Arrays;
import java.util.Comparator;
public class Anon {
abstract static class Discount {
final String name;
Discount(String name) { this.name = name; }
abstract long apply(long amount);
}
public static void main(String[] args) {
Discount festival = new Discount("Festival 10%") {
long apply(long amount) { return amount - amount / 10; }
};
System.out.println(festival.name + ": Rs. " + festival.apply(2000));
String[] names = {"Srihitha", "Navika", "Advitha"};
Arrays.sort(names, new Comparator<String>() {
public int compare(String a, String b) {
return Integer.compare(a.length(), b.length());
}
});
System.out.println(Arrays.toString(names));
Arrays.sort(names, (a, b) -> b.compareTo(a));
System.out.println(Arrays.toString(names));
System.out.println(festival.getClass().getName());
}
}Festival 10%: Rs. 1800
[Navika, Advitha, Srihitha]
[Srihitha, Navika, Advitha]
Anon$1How it works
new Discount("Festival 10%") { ... }creates an object of a new, unnamed subclass ofDiscount. The argument goes toDiscount's constructor, and the body implements the abstract method.new Comparator<String>() { ... }creates an object of an unnamed class that implementsComparator, here sorting names by length.- The third sort uses a lambda,
(a, b) -> b.compareTo(a), which is a much shorter way to implement an interface with a single abstract method (lambdas get their own lessons later in the course). - The compiler names the first anonymous class
Anon$1.
The Rules
| Rule | Detail |
|---|---|
| Extends or implements | Exactly one class or one interface |
| Constructor | None of its own; arguments go to the parent's constructor. Use an instance initializer block { ... } for setup |
| Name | None, so it can't be created again or used as a type |
| Access to the surrounding code | Outer instance members, and local variables that are effectively final |
| New methods | Allowed, but callable only from inside it (the variable's type doesn't know them) |
| Class file | Outer$1.class, Outer$2.class, ... |
Capturing a local variable that changes later is a compile error:
public class Eff {
void run() {
int count = 0;
Runnable r = new Runnable() {
public void run() { System.out.println(count); }
};
count++;
}
}Eff.java:5: error: local variables referenced from an inner class must be final or effectively final
public void run() { System.out.println(count); }
^
1 errorThe anonymous object gets a copy of count; if count could change afterwards, the copy and the original would disagree, so Java forbids it.
Anonymous Class or Lambda?
| Use a lambda when | Use an anonymous class when |
|---|---|
Implementing an interface with one abstract method (Comparator, Runnable) | Extending a class, especially an abstract one |
| The code is short | Implementing several methods |
You don't need this to mean the implementing object | You need fields or state in the object |
Common Mistakes
Changing a captured local variable. Use a final copy, or a field.
Long anonymous classes buried inside method calls. If it's longer than a few lines, give it a name.
Expecting extra methods to be callable from outside. festival.extraMethod() doesn't compile: the variable's type is Discount.
Interview Corner
What is an anonymous inner class?
It's a class without a name, declared and instantiated in a single expression with new Type(args) { ... }. It either extends one class or implements one interface, can't declare constructors, and can access effectively final local variables and the enclosing instance. It's used for one-off implementations; since Java 8, lambdas replace most anonymous classes that implement single-method interfaces.
Can an anonymous class have a constructor?
No, because it has no name to give the constructor. Arguments in new Type(args) are passed to the superclass constructor, and an instance initializer block can do any extra setup.
Practice
- Easy: Create a
Runnablewith an anonymous class that prints "Backup started for Navika", and run it withr.run(). - Harder: Sort an array of prices in descending order twice: once with an anonymous
Comparator<Integer>and once with a lambda.
Key Takeaways
Was this tutorial helpful?