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.
public class Main { public static void main(String[] args) { Greeter polite = new Greeter() { public String greet(String name) { return "Good morning, " + name + "."; } }; System.out.println(polite.greet("Ada")); }} interface Greeter { String greet(String name);}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:
newcreates an object, as it always does.Greeteris 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 ispublicbecause 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 ideaAn anonymous class expression does two jobs at once: it declares a new class with no name, and it creates one object of that class.
';' 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:
import java.util.ArrayList;import java.util.Comparator;import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = new ArrayList<>(List.of("banana", "fig", "cherry", "kiwi")); Comparator<String> byLength = new Comparator<>() { public int compare(String a, String b) { return Integer.compare(a.length(), b.length()); } }; fruits.sort(byLength); System.out.println(fruits); }}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.
public class Main { public static void main(String[] args) { double side = 3.0; Shape square = new Shape("square") { double area() { return side * side; } }; square.describe(); Counter loud = new Counter() { void add() { super.add(); System.out.println("count is now " + count); } }; loud.add(); loud.add(); }} abstract class Shape { String name; Shape(String name) { this.name = name; } abstract double area(); void describe() { System.out.println(name + " has area " + area()); }} class Counter { int count; void add() { count++; }}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.
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:
public class Main { public static void main(String[] args) { Bakery bakery = new Bakery("Crumbs"); Greeter door = bakery.doorGreeter(); System.out.println(door.greet("Ada")); bakery.name = "Crumbs and Co"; System.out.println(door.greet("Ada")); }} interface Greeter { String greet(String customer);} class Bakery { String name; Bakery(String name) { this.name = name; } Greeter doorGreeter() { return new Greeter() { public String greet(String customer) { return "Welcome to " + name + ", " + customer + "!"; } }; }}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:
public class Main { public static void main(String[] args) { int presses = 0; Button ok = new Button() { public void press() { presses++; System.out.println("Presses so far: " + presses); } }; ok.press(); }} interface Button { void press();}$ javac Main.javaMain.java:7: error: local variables referenced from an inner class must be final or effectively final presses++; ^1 errorTo 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.
public class Main { public static void main(String[] args) { Ticket ticket = new Ticket() { String prefix; int issued; { prefix = "A-"; log("machine ready"); } public String next() { issued++; log("issued " + issued); return prefix + issued; } void log(String message) { System.out.println("[ticket] " + message); } }; System.out.println(ticket.next()); System.out.println(ticket.next()); }} interface Ticket { String next();}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 withinvalid 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 withanonymous 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")inmainfails withcannot find symbol, becauseticketis aTicket, andTickethas nolog.
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:
public class Main { public static void main(String[] args) { Greeter polite = new Greeter() { public String greet(String name) { return "Good morning, " + name + "."; } }; Greeter casual = name -> "Hey " + name + "!"; System.out.println(polite.greet("Ada")); System.out.println(casual.greet("Ada")); }} interface Greeter { String greet(String name);}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.
this means the anonymous object.this means the enclosing object, the same as outside the lambda.Main$1.class.What this means inside each one#
The this row surprises people. Decide what this program prints, then run it.
public class Main { public static void main(String[] args) { Robot robot = new Robot("R2"); robot.test(); }} interface Speaker { String speak();} class Robot { String name; Robot(String name) { this.name = name; } public String toString() { return "Robot " + name; } void test() { Speaker anon = new Speaker() { public String speak() { return "anonymous class: " + this; } public String toString() { return "a Speaker with no name"; } }; Speaker lambda = () -> "lambda: " + this; System.out.println(anon.speak()); System.out.println(lambda.speak()); }}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:
import java.util.ArrayList;import java.util.Comparator;import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = new ArrayList<>(List.of("banana", "fig", "cherry", "kiwi")); fruits.sort(Comparator.comparingInt(String::length)); fruits.forEach(System.out::println); }}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
newand 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
thismeans 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::lengthmeans the same ass -> s.length().- What are unnamed classes in Java?
- Unnamed classes were a Java 21 preview feature that let a source file hold a
mainmethod 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#
- Anonymous Classes, in Oracle's Java Tutorials
- Anonymous class declarations, Java Language Specification (Java SE 25), section 15.9.5
- When to use nested classes, local classes, anonymous classes and lambda expressions, in Oracle's Java Tutorials
- JEP 512: Compact Source Files and Instance Main Methods, final in Java 25