44

In java 8, an abstract class with only one abstract method is not a functional interface (JSR 335).

This interface is a functional interface:

public interface MyFunctionalInterface {
    public abstract void myAbstractMethod();
    public default void method() {
        myAbstractMethod();
    }
}

but this abstract class is not:

public abstract class MyFunctionalAbstractClass {
    public abstract void myAbstractMethod();
    public void method() {
        myAbstractMethod();
    }
}

So i can't use the abstract class as a target for a lambda expressions and method references.

public class Lambdas {
    public static void main(String[] args) {
        MyFunctionalAbstractClass functionalAbstractClass = () -> {};
    }
}

The compilation error is: The target type of this expression must be a functional interface.

Why the language designers imposed this restriction ?

gontard
  • 28,720
  • 11
  • 94
  • 117

1 Answers1

42

This has been an important topic since the very inception of the Lambda project and has received a lot of thought. Brian Goetz, the chief Java Language architect, strongly supports the view of lambda as a function, not an object. Quote:

It is my belief that the best direction for evolving Java is to encourage a more functional style of programming. The role of Lambda is primarily to support the development and consumption of more functional-like libraries

I am optimistic about Java's future, but to move forward we sometimes have to let go of some comfortable ideas. Lambdas-are-functions opens doors. Lambdas-are-objects closes them. We prefer to see those doors left open.

Here is a link to the quote's source and here is Brian's more recent post which reiterates the same philosophical points and reaffirms them with additional, more practical arguments:

Making the model simpler opens doors to all sorts of VM optimizations. (Jettisoning identity is key here.) Functions are values. Modeling them as objects makes them heavier, and more complex, than they need to be.

Before throwing this use case under the bus, we did some corpus analysis to found how often abstract class SAMs are used compared to interface SAMs. We found that in that corpus, only 3% of the lambda candidate inner class instances had abstract classes as their target. And most of them were amenable to simple refactorings where you added a constructor/factory that accepted a lambda that was interface-targeted.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 20
    I will just add that this was one of the most hotly debated topics in the early phase of JSR-335. When we first suggested the "interfaces only" rule, it seemed risky. But as this has now had several years to settle, I am absolutely convinced we did the right thing. We gained significant simplicity and flexibility (which accrues to all users in the form of better performance and more flexible future language evolution) for having dropped a few corner-case use cases. – Brian Goetz Jul 07 '14 at 19:31
  • I don't see Brian Goetz provided any THOUGHTS here. Just some senseless WORDS. Lambdas are syntactic sugar for anonymous inner classes. Then why add bitter to sugar?! – Dims Dec 20 '16 at 13:42
  • Legacy Java _happened to_ not have first-class functions, and it _happened to_ add the awkward feature of anon inner classes to address the gap. Past decisions are, at best, on an equal footing with new decisions and there is no benefit to treating them as dogma. Lambdas aren't "syntactic sugar for anonymous classes", it is anonymous classes that are the hack to be dealt with. – Marko Topolnik Dec 03 '22 at 09:40