Learn Java

Anonymous Inner Class in Java, with Examples

By Updated 8 min read

An anonymous inner class in Java is a class with no name that you define and create an object of in one expression, by putting a class body in braces right after new and the name of an interface or class. Use one when you need a class in exactly one place, such as a one-off implementation of an interface. Every example below runs in the page: how to write one, the two ways to use it, the rules for variables and this, and when a lambda fits better.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Greeter polite = new Greeter() {
4 public String greet(String name) {
5 return "Good morning, " + name + ".";
6 }
7 };
8
9 System.out.println(polite.greet("Ada"));
10 }
11}
12
13interface Greeter {
14 String greet(String name);
15}
Prints
›Good morning, Ada.

It prints Good morning, Ada. The variable polite holds an object of a class that has no name in the code. Press Run and look at the memory view: it shows one object of class Main$1, the name the compiler gives the class behind the scenes.

How to write an anonymous class#

The general shape is new Type(arguments) { class body }. Read the example's new Greeter() { ... }; from left to right:

  • new creates an object, as it always does.
  • Greeter is the type the new class builds on: an interface to implement, or a class to extend.
  • () holds the arguments for a constructor. An interface has no constructor, so here the parentheses stay empty.
  • The braces hold the class body, written the way you write any class: fields and methods. This body has one method, greet. It is public because the methods an interface asks for are always public, and a class may not offer one with less access.
  • The semicolon after the closing brace ends the statement. The whole thing is one expression inside an ordinary variable declaration.
Key idea

An anonymous class expression does two jobs at once: it declares a new class with no name, and it creates one object of that class.

The semicolon after the brace
A named class ends at its closing brace, so beginners often stop there. An anonymous class sits inside a statement, and without the semicolon javac stops with ';' expected, pointing just past the brace.

Implement an interface with an anonymous class#

Implementing an interface is the most common use. You cannot write new Greeter() on its own, because Greeter leaves its method for a class to write: javac says Greeter is abstract; cannot be instantiated. Add a body that supplies the missing method, and Java has a complete class to build an object from.

Interfaces from Java's library work the same way. Comparator<String> has one method to fill in, compare, which returns a negative number, zero or a positive number to say which of two strings comes first. This one sorts fruit by the length of the name:

Main.java
1import java.util.ArrayList;
2import java.util.Comparator;
3import java.util.List;
4
5public class Main {
6 public static void main(String[] args) {
7 List<String> fruits = new ArrayList<>(List.of("banana", "fig", "cherry", "kiwi"));
8
9 Comparator<String> byLength = new Comparator<>() {
10 public int compare(String a, String b) {
11 return Integer.compare(a.length(), b.length());
12 }
13 };
14
15 fruits.sort(byLength);
16 System.out.println(fruits);
17 }
18}
Prints
›[fig, kiwi, banana, cherry]

It prints [fig, kiwi, banana, cherry]. Integer.compare returns a negative number when a is shorter, so shorter names go first. banana and cherryboth have six letters, and they keep their original order, because Java's list sort never reorders items that compare as equal.

The empty <> after Comparator is the diamond: Java works out Stringfrom the variable's type. Anonymous classes accept the diamond since Java 9. Older code spells it out as new Comparator<String>().

Extend a class with an anonymous class#

The name after new can also be a class. The anonymous class then extends it and can override its methods. If the class is abstract (it leaves some methods unwritten, so you cannot create one directly), the anonymous class must write every missing method. If it is an ordinary class, the anonymous class overrides only what it wants to change.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 double side = 3.0;
4 Shape square = new Shape("square") {
5 double area() {
6 return side * side;
7 }
8 };
9 square.describe();
10
11 Counter loud = new Counter() {
12 void add() {
13 super.add();
14 System.out.println("count is now " + count);
15 }
16 };
17 loud.add();
18 loud.add();
19 }
20}
21
22abstract class Shape {
23 String name;
24
25 Shape(String name) {
26 this.name = name;
27 }
28
29 abstract double area();
30
31 void describe() {
32 System.out.println(name + " has area " + area());
33 }
34}
35
36class Counter {
37 int count;
38
39 void add() {
40 count++;
41 }
42}
Prints
›square has area 9.0
›count is now 1
›count is now 2

It prints square has area 9.0, then count is now 1 and count is now 2. The "square" in the parentheses goes to Shape's constructor: arguments after new always go to the constructor of the class being extended. Inside the second class, super.add() runs Counter's own add first, as in any subclass. Step through it and the trace jumps into the Shape constructor while the first object is being built.

Every abstract method must be written
Leave area() out of the first anonymous class and javac refers to the class by the name it made up: <anonymous Main$1> is not abstract and does not override abstract method area() in Shape.

Why is it called an inner class?#

An inner class is a class written inside another class without the word static. Each of its objects belongs to one object of the outer class, the enclosing object, and can use that object's fields directly. An anonymous class written inside an instance method (a method without static, which runs on an object) is an inner class in this sense:

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Bakery bakery = new Bakery("Crumbs");
4 Greeter door = bakery.doorGreeter();
5 System.out.println(door.greet("Ada"));
6
7 bakery.name = "Crumbs and Co";
8 System.out.println(door.greet("Ada"));
9 }
10}
11
12interface Greeter {
13 String greet(String customer);
14}
15
16class Bakery {
17 String name;
18
19 Bakery(String name) {
20 this.name = name;
21 }
22
23 Greeter doorGreeter() {
24 return new Greeter() {
25 public String greet(String customer) {
26 return "Welcome to " + name + ", " + customer + "!";
27 }
28 };
29 }
30}
Prints
›Welcome to Crumbs, Ada!
›Welcome to Crumbs and Co, Ada!

It prints Welcome to Crumbs, Ada!, then Welcome to Crumbs and Co, Ada!. Inside greet, nameis the bakery's field, read at the moment the method runs, so the greeter sees the new name. Step through it and look at the Bakery$1 object in the memory view: its only row is Bakery.this, a hidden link back to the bakery that created it.

The earlier examples on this page sit in main, which is static and runs on no object, so their anonymous classes have no such link. Named inner classes and static nested classes are covered in the inner classes lesson.

Using local variables: the effectively final rule#

An anonymous class can read the local variables of the method around it, as the shape example read side, but only if each one keeps a single value. Java calls such a variable effectively final: it has no final keyword, but it could have one. Give the variable a second value anywhere, inside the anonymous class or outside it, and the program no longer compiles. The usual way to hit this is counting something:

Main.java (does not compile)
read along
1public class Main {
2 public static void main(String[] args) {
3 int presses = 0;
4
5 Button ok = new Button() {
6 public void press() {
7 presses++;
8 System.out.println("Presses so far: " + presses);
9 }
10 };
11 ok.press();
12 }
13}
14
15interface Button {
16 void press();
17}
Terminal
read along
1$ javac Main.java
2Main.java:7: error: local variables referenced from an inner class must be final or effectively final
3 presses++;
4 ^
51 error

To count, keep the number in a field instead, since fields may change freely. It can be a field of the anonymous object itself, as in the next section, or a field of the enclosing object.

What an anonymous class can and cannot have#

The body can hold fields and as many methods as you like, with one exception: no constructor, since a constructor must carry the class's name. For setup, you have two options. Pass arguments to the parent class's constructor in the parentheses, as Shape did, or write an instance initializer: a bare block of code in braces inside the class body, which runs each time an object of the class is created.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Ticket ticket = new Ticket() {
4 String prefix;
5 int issued;
6
7 {
8 prefix = "A-";
9 log("machine ready");
10 }
11
12 public String next() {
13 issued++;
14 log("issued " + issued);
15 return prefix + issued;
16 }
17
18 void log(String message) {
19 System.out.println("[ticket] " + message);
20 }
21 };
22
23 System.out.println(ticket.next());
24 System.out.println(ticket.next());
25 }
26}
27
28interface Ticket {
29 String next();
30}
Prints
›[ticket] machine ready
›[ticket] issued 1
›A-1
›[ticket] issued 2
›A-2

It prints [ticket] machine ready first, while new builds the object, then [ticket] issued 1, A-1, [ticket] issued 2 and A-2. The field issued changes on every call, which is allowed because it belongs to the object, not to main. log is an extra method that Ticket knows nothing about, called from inside the class. The limits:

  • No constructor of its own. Writing Ticket() { ... } in the body fails with invalid method declaration; return type required, because to javac it looks like a method with its return type missing.
  • One parent type. It extends one class or implements one interface, never both, and never two interfaces.
  • No arguments for an interface. new Ticket("A-") { ... } fails with anonymous class implements interface; cannot have arguments.
  • No name to reuse. The expression can run many times, in a loop or in a method you call twice, and makes a new object of the same class each time, but no other line can create one by name. If you need the class in two places, give it a name.
  • Code outside sees only the parent type. ticket.log("hi") in main fails with cannot find symbol, because ticket is a Ticket, and Ticket has no log.

Anonymous class vs lambda expression#

A lambda expression is a shorter way to create an object of a functional interface, an interface with exactly one abstract method: you write only the parameters, an arrow and the body. Lambdas arrived in Java 8, and since then most anonymous classes that implement a one-method interface have given way to lambdas. Here is the same Greeter both ways:

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Greeter polite = new Greeter() {
4 public String greet(String name) {
5 return "Good morning, " + name + ".";
6 }
7 };
8 Greeter casual = name -> "Hey " + name + "!";
9
10 System.out.println(polite.greet("Ada"));
11 System.out.println(casual.greet("Ada"));
12 }
13}
14
15interface Greeter {
16 String greet(String name);
17}
Prints
›Good morning, Ada.
›Hey Ada!

It prints Good morning, Ada. and Hey Ada!. The lambda leaves out new Greeter(), the method header and the braces, because the compiler can work all of them out from the variable's type.

Anonymous class
Lambda expression
Implements an interface with any number of methods, or extends a class, abstract or not.
Implements only an interface with exactly one abstract method.
Can have fields, several methods and an instance initializer, so it can keep state between calls.
Is the body of one method. It cannot declare fields of its own.
this means the anonymous object.
this means the enclosing object, the same as outside the lambda.
Compiles to a class file of its own, such as Main$1.class.
Gets no class file. javac turns its body into a private method of the enclosing class, and the object is made while the program runs.
Local variables it uses must be effectively final.
The same rule.
Choose it when you need fields, more than one method, or a class to extend.
Choose it for a single action on a functional interface.

What this means inside each one#

The this row surprises people. Decide what this program prints, then run it.

Predict the outputMain.java
1public class Main {
2 public static void main(String[] args) {
3 Robot robot = new Robot("R2");
4 robot.test();
5 }
6}
7
8interface Speaker {
9 String speak();
10}
11
12class Robot {
13 String name;
14
15 Robot(String name) {
16 this.name = name;
17 }
18
19 public String toString() {
20 return "Robot " + name;
21 }
22
23 void test() {
24 Speaker anon = new Speaker() {
25 public String speak() {
26 return "anonymous class: " + this;
27 }
28
29 public String toString() {
30 return "a Speaker with no name";
31 }
32 };
33 Speaker lambda = () -> "lambda: " + this;
34
35 System.out.println(anon.speak());
36 System.out.println(lambda.speak());
37 }
38}

Robot has its own toString, and so does the anonymous class. What do the two lines show?

It prints anonymous class: a Speaker with no name, then lambda: Robot R2. Inside the anonymous class, this is the anonymous object, so the text comes from its own toString. A lambda does not change what this means, so inside it this is the robot, as anywhere else in test. To reach the robot from inside the anonymous class, write Robot.this.

What does :: mean in Java?#

:: makes a method reference, an even shorter lambda for when the lambda only calls a method that already exists. String::length means s -> s.length(), and System.out::println means x -> System.out.println(x). Here is the length comparator from earlier, down to one line:

Main.java
1import java.util.ArrayList;
2import java.util.Comparator;
3import java.util.List;
4
5public class Main {
6 public static void main(String[] args) {
7 List<String> fruits = new ArrayList<>(List.of("banana", "fig", "cherry", "kiwi"));
8
9 fruits.sort(Comparator.comparingInt(String::length));
10 fruits.forEach(System.out::println);
11 }
12}
Prints
›fig
›kiwi
›banana
›cherry

It prints fig, kiwi, banana and cherry, one per line, in the same order the anonymous Comparator gave. Comparator.comparingInt builds the comparator from a rule that turns each string into a number. There are four kinds of method reference: a static method (Integer::parseInt), a method of one particular object (System.out::println), a method of whichever object is passed in (String::length), and a constructor (ArrayList::new). The lambdas lesson teaches lambdas and method references from the start.

Anonymous classes are not unnamed classes#

“Unnamed class” sounds like another word for an anonymous class, but it was the name of a different feature: a source file that holds a main method with no class written around it. Java 21 previewed it as unnamed classes (JEP 445), later previews renamed it implicitly declared classes, and Java 25 made it final as compact source files with instance main methods (JEP 512). In Java 25, a file that contains only void main() { IO.println("Hi"); } is a complete program, and Java wraps it in a class that it declares for you.

The two share only the idea of a class you never name. An anonymous class is an expression inside a program that makes one object; a compact source file is a whole program. Compact source files are where your first Java program starts.

Questions people ask#

What is an anonymous inner class in Java?
It is a class with no name that you define and create one object of in a single expression, by writing a class body in braces after new and an interface or class name. You use it when a class is needed in one place only, such as a one-off implementation of an interface.
What does inner class mean in Java?
An inner class is a class declared inside another class without static. Its objects belong to an object of the outer class and can use that object's fields directly. An anonymous class written in an instance method is an inner class in this sense.
What is the difference between an anonymous inner class and a lambda expression?
A lambda can only implement an interface with exactly one abstract method, while an anonymous class can implement any interface or extend a class, and can have fields and several methods. Inside an anonymous class this means the anonymous object, while inside a lambda it means the enclosing object.
Can an anonymous class have a constructor?
No, because a constructor must carry the class's name and an anonymous class has none. Pass arguments to the parent class's constructor in the parentheses after new, or put setup code in an instance initializer block.
What does :: mean in Java?
:: makes a method reference, a shorter way to write a lambda that only calls a method that already exists. String::length means the same as s -> s.length().
What are unnamed classes in Java?
Unnamed classes were a Java 21 preview feature that let a source file hold a main method with no class written around it. Java 25 made that feature final under the name compact source files, and it has nothing to do with anonymous classes.

Further reading#

Learn it step by step

These lessons teach the topic from the start, with more examples and questions to check yourself.

All guides

Spotted a mistake, or a part that did not make sense? Report it by email