Why do I need a functional Interface to work with lambdas?

codepleb picture codepleb · Oct 8, 2015 · Viewed 29.4k times · Source

I think this question is already somewhere out there, but I wasn't able to find it.

I don't understand, why it's necessary to have a functional interface to work with lambdas. Consider the following example:

public class Test {

    public static void main(String...args) {
        TestInterface i = () -> System.out.println("Hans");
//      i = (String a) -> System.out.println(a);

        i.hans();
//      i.hans("Hello");
    }
}

public interface TestInterface {
    public void hans();
//  public void hans(String a);
}

This works without problems, but if you uncomment the commented lines, it doesn't. Why? In my understanding, the compiler should be able to distinguish the two methods, since they have different input-parameters. Why do I need a functional interface and blow up my code?

EDIT: The linked duplicates didn't answer my question because I'm asking about different method-parameters. But I got some really useful answers here, thanks to everyone who helped! :)

EDIT2: Sorry, I'm obviously not a native speaker, but to precise myself:

public interface TestInterface {
    public void hans();                 //has no input parameters</br>
    public void hans(String a);         //has 1 input parameter, type String</br>
    public void hans(String a, int b);  //has 2 input parameters, 1. type = String, 2. type = int</br>
    public void hans(int a, int b);     //has also 2 input parameters, but not the same and a different order than `hans(String a, int a);`, so you could distinguish both
}

public class Test {

    public static void main(String...args) {
        TestInterface i = () -> System.out.println("Hans");
        i = (String a) -> System.out.println(a);
        i = (String a, int b) -> System.out.println(a + b);
        i = (int a, int b) -> System.out.println(a);

        i.hans(2, 3);   //Which method would be called? Of course the one that would take 2 integer arguments. :)
    }
}

All I'm asking is about the arguments. The method name doesn't matter, but each method takes an unique order of different arguments and because of that, Oracle could have implemented this feature instead just making a single method possible per "Lambda-Interface".

Answer

Eran picture Eran · Oct 8, 2015

When you write :

TestInterface i = () -> System.out.println("Hans");

You give an implementation to the void hans() method of the TestInterface.

If you could assign a lambda expression to an interface having more than one abstract method (i.e. a non functional interface), the lambda expression could only implement one of the methods, leaving the other methods unimplemented.

You can't solve it by assigning two lambda expressions having different signatures to the same variable (Just like you can't assign references of two objects to a single variable and expect that variable to refer to both objects at once).