Anonymous Class vs Lambda

Naveen AnamaneniUpdated · 4 min read

Before Java 8, the shortest way to pass behavior to a method was an anonymous class: a class with no name, declared and created in one expression (see "Anonymous Inner Class in Java"). Since Java 8, a lambda expression does the same job in far less code, but only for functional interfaces. They look similar, but they are not the same thing: they differ in what this means, what they can hold, and how they are compiled. In this lesson, you will compare them side by side.

Example: The Same Comparator, Two Ways

Let's see an example that sorts names by length with each.

TwoWays.java▶ Try it
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
 
public class TwoWays {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(
            List.of("Srihitha", "Navika", "Anamaneni", "Advitha"));
 
        names.sort(new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return Integer.compare(a.length(), b.length());
            }
        });
        System.out.println("Anonymous class: " + names);
 
        names.sort((a, b) -> Integer.compare(b.length(), a.length()));
        System.out.println("Lambda:          " + names);
    }
}
Output
Anonymous class: [Navika, Advitha, Srihitha, Anamaneni]
Lambda:          [Anamaneni, Srihitha, Advitha, Navika]

Explanation: The anonymous class needs the interface name, the method signature and @Override: six lines for one comparison. The lambda states only the parameters and the logic, in one line. The lambda here sorts longest first, just to show a different order.

The Meaning of this

Inside an anonymous class, this refers to the anonymous class object. Inside a lambda, this refers to the enclosing object, because a lambda isn't a separate object with its own identity:

ThisDemo.java▶ Try it
public class ThisDemo {
    private final String name = "outer ThisDemo";
 
    @Override
    public String toString() {
        return name;
    }
 
    void run() {
        Runnable anon = new Runnable() {
            @Override
            public void run() {
                System.out.println("anonymous this: "
                    + this.getClass().getSimpleName().isEmpty());
            }
        };
        Runnable lambda = () -> System.out.println("lambda this: " + this);
        anon.run();
        lambda.run();
    }
 
    public static void main(String[] args) {
        new ThisDemo().run();
    }
}
Output
anonymous this: true
lambda this: outer ThisDemo

Explanation: In the anonymous class, this is the anonymous object, whose class has no simple name, so getSimpleName() is empty. In the lambda, this is the ThisDemo object that created it, so its toString prints "outer ThisDemo".

Differences Between Anonymous Class and Lambda

Anonymous classLambda expression
Can implementAny interface (any number of methods) or extend a classOnly a functional interface
SyntaxVerbose: new Type() { ... }Short: (params) -> body
Meaning of thisThe anonymous objectThe enclosing object
Fields and stateCan declare fieldsCan't declare fields
Extra methodsCan add helper methodsCan't
Shadowing local variable namesAllowedNot allowed
Compiled toA separate .class file (Outer$1.class)No extra class file; created at runtime with invokedynamic
Captured local variablesMust be effectively finalMust be effectively final

Common Mistakes

Trying to use a lambda for an interface with two abstract methods. It doesn't compile; use an anonymous class or a named class.

Expecting this in a lambda to be the lambda. It's the surrounding object.

Declaring a lambda parameter with the same name as a local variable. It doesn't compile, while an anonymous class would allow it.

Interview Corner

What is the difference between an anonymous class and a lambda?

An anonymous class is a real unnamed class: it can implement any interface or extend a class, have fields and several methods, and inside it this refers to the anonymous object; the compiler generates a separate class file for it. A lambda can only implement a functional interface, has no fields or extra methods, treats this as the enclosing instance, can't shadow local variables, and is created at runtime through invokedynamic without a separate class file. Lambdas are shorter and usually more efficient.

Practice

  1. Easy: Rewrite an anonymous Runnable that prints "Navika" as a lambda.
  2. Harder: Write an anonymous Iterator<Integer> that counts from 1 to 5 using a field. Explain why it can't be written as a lambda.

Quick check: Anonymous class vs lambda

4 questions
1Which can implement an interface with two abstract methods?
2In a lambda, what does this refer to?
3Can a lambda declare fields?
4Which one creates a separate .class file at compile time?

Key Takeaways

Was this tutorial helpful?

Lesson 304 of 482