Introduction

In this article, we will understand how to convert an anonymous class into a Lambda expression in java with detailed examples and their explanation.

Anonymous Class
Anonymous classes in java allow you to define a class without giving it a name. Anonymous literally means Without a name.

Anonymous classes are used when you need to implement an interface or extend a class, but only need to use the class once.
Anonymous classes can be created by using new keyword, followed by the class or interface you want to extend or implement, and then the class definition inside curly braces.
Lambda expression
Lambda expression is an implementation of a method defined in an interface. The implementation method will be anonymous meaning it will have NO name.
So, indirectly, a lambda expression is a shorthand way to create an anonymous class that implements a functional interface.

Convert anonymous class to Lambda expression
In Java, you can convert an anonymous class into a lambda expression by following below steps.
1. Remove the new operator and class name.
2. Add an arrow(->) between the parenthesis and curly braces, which contain the definition of anonymous class.
3. Replace the method body with its implementation. That is, remove the method signature and its starting and ending curly braces.

Here’s an example of converting an anonymous class that implements the Runnable interface into a lambda expression:

// Anonymous class
Runnable runnable = new Runnable() {
    public void run() {
        System.out.println("Hello, World!");
    }
};

// Lambda equivalent
Runnable runnable = () -> System.out.println("Hello, World!");

Remember that you can use this approach only if the anonymous class implements exactly one interface.
If the class implements more than one interface, you will have to explicitly specify the functional interface the lambda is implementing. We will see this later in the article.

Examples
Below are some of the examples which demonstrate implementations using anonymous class and their lambda equivalent.

1. Anonymous class that implements the Comparator interface

Comparator<Integer> comparator = new Comparator<Integer>() {
    public int compare(Integer a, Integer b) {
        return a.compareTo(b);
    }
};

Corresponding lambda equivalent

Comparator<Integer> comparator = (a, b) -> a.compareTo(b);

2. Anonymous class that extends the Thread class

Thread thread = new Thread() {
    public void run() {
        System.out.println("Hello, World!");
    }
};

Corresponding lambda equivalent

Thread thread = () -> System.out.println("Hello, World!");

3. Anonymous class that implements the ActionListener interface

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button clicked!");
    }
});

Corresponding lambda equivalent

button.addActionListener(e -> System.out.println("Button clicked!"));

Overloaded methods in class
As stated earlier, an anonymous class is an implementation of a method in a class or interface that anonymous class extends or implements.
And a lambda expression is an implementation of a functional interface.

So, if a class has multiple overloaded methods that accept different functional interfaces as arguments, and you want to use a lambda expression as the argument, you have to make sure that the lambda expression you are passing as an argument matches the functional interface expected by the overloaded method.

Here’s an example of a class that has two overloaded methods, one that accepts a Predicate<Integer> and the other that accepts a Function<Integer, String>

class Example {
    public void test(Predicate<Integer> p) {
        System.out.println("Predicate method");
    }

    public void test(Function<Integer, String> f) {
        System.out.println("Function method");
    }
}

Now if you want to pass a lambda expression as an argument to the test() method, you have to make sure that the lambda expression matches the functional interface expected by the method

Example ex = new Example();
// This will invoke the method which accepts Predicate
ex.test(x -> x > 5);  
// This will invoke the method which accepts Function
ex.test(x -> "Number : " + x);  

In this example, the first lambda expression x -> x > 5 matches the Predicate<Integer> functional interface and the second lambda expression x -> "Number : " + x matches the Function<Integer, String> functional interface, so the Java compiler knows which overloaded method to invoke.

In case both the lambda expressions match with the functional interfaces accepted by the overloaded methods, the compiler will give an error as it will not know which overloaded method to invoke.
In such cases, we can use the explicit casting to the functional interface to invoke the desired method as shown below

// This will invoke the method which accepts Predicate
ex.test((Predicate<Integer>) x -> "Number : " + x);  

Note that, to convert an anonymous class to a lambda expression, the anonymous class should be implementing exactly one functional interface.
If the class implements more than one functional interface, you will have to explicitly specify the functional interface the lambda is implementing.

Hope the article was useful.