Lambda Expressions for Abstract Classes

No, You can't do it. Lambdas have to target single abstract method (SAM) on interfaces, and they don't work with single abstract method on abstract classes. This how it is, and you have to accept it,

Although it makes sense to have them, the language designers decided that it is not worth the complexity that will be introduced by allowing lambdas on SAM abstract classes.

As a reference, thats what Brian Goetz said about allowing lambdas on SAM abstract class.

Main key-points from Brian's email:

  • only 3% of the lambda candidate inner class instances had abstract classes as their target

  • Complicating the model for the sake of a few-percent-use-case seemed a bad trade


You cannot directly make a lambda expression target an abstract class, as Sleiman Jneidi pointed out in his answer. However, you can use a workaround:

public class AbstractLambda<T> extends Abstract<T>
{
    private final Supplier<? extends T> supplier;
    public AbstractLambda(Supplier<? extends T> supplier)
    {
        this.supplier = supplier;
    }

    @Override
    public T getSomething()
    {
        return this.supplier.get();
    }
}

This can be used with a lambda expression:

Abstract<String> a = new AbstractLambda<>(() -> "Hello World");
System.out.println(a.getSomething()); // prints 'Hello World'

In case your getSomething(...) method has arguments, use a java.util.function.Function or the appropriate interface from the java.util.function package instead of java.util.function.Supplier.


This is also how the java.lang.Thread lets you use a Runnable lambda instead of having to subclass the class:

Thread t = new Thread(() -> System.out.println("Hello World"));
t.start();

Tags:

Java

Lambda