Why to use @FunctionalInterface annotation in Java 8
Asked Answered
S

4

17

If we have Interface with only one abstract method in it, it is by default Functional Interface. Can anyone please explain what additional advantage @FunctionalInterface annotation brings?

I know that if we add @FunctionalAnnotation, it will not allow someone to add another abstract method in the interface, as it will give a compilation error, but my point is even if you don't use @FucntionalInterface annotation, then also, if someone will add another abstract method, it will break all the existing lambda expressions in the code and compiler will complain.

For example:

If I have the following Interface:

public interface User {
    
    Integer fetchData(Integer userId);
}

with following implementation:

public class UserImpl implements User{

    @Override
    public Integer fetchData(Integer userId) {
        return 1;
    }
}

and following usage :

public class TestFunctionalInterface {
    
    public static void main(String[] args) {
        User user = a -> a*2;
        System.out.println("FetchedData:"+user.fetchData(2));
    }

}

And now, if I try to add another method in the interface like below:

public interface User {
    
    Integer fetchData(Integer userId);
    
    Integer fetchLoginDetails(Integer userId);

}

Compiler is complaining in below code:

public class TestFunctionalInterface {
    
    public static void main(String[] args) {
        User user = a -> a*2;
        System.out.println("FetchedData:"+user.fetchData(2));
    }

}

at line User user = a -> a*2;

With message "The target type of this expression must be a functional interface".

Scandian answered 16/6, 2018 at 22:0 Comment(4)
Except if you don't have any lambda of that type in your compilation unit. It also serves as documentation. And some SAM interfaces are not intended to be defined as lambda expressions. See #28166687Headland
@JB Nizet, Thanks for your response.if I don't have any lambda in my compilation unit, even in that case if I am adding another method in interface which is abstract,I should be quite sure that all classes which are going to implement this interface are going to fail,as they need to implement this new method.Scandian
Except if you don't have any concrete implementation of this interface in your compilation unit. You might write a library, defining an interface, but not implementing it yourself. And again, it also serves to document that this interface is designed to be implemented as a lambda expression.Headland
Possible duplicate of What is use of Functional Interface in Java 8?Allometry
I
2

The main advantage to protect your interface by @FunctionalInterface is when you use lambda to instantiate them.

Lambda declaration can only declare one block of code so if there is no protection on your interface and some will add an abstract method your lambda have no more sense ...

that why its highly recommend to not implement with lambda some implicit functional interface.

So if you want to implement this interface by lambda way I encourage you to add the annotation that s a security. if you don't want this kind of implementation or if your interface will change or have an night risk to change don t had it.

Inessa answered 16/6, 2018 at 22:13 Comment(1)
The accepted answer completely misses the point of the question. See Ronan's answer instead.Corrincorrina
A
10

A compilation error would not occur if a different module was using the interface, for example if the interface was available via a dependency. Someone using your module can safely use the function in a lambda without fearing that a later update will break their code.

Allianora answered 16/6, 2018 at 22:5 Comment(0)
F
8

The functional interface can have only ONE abstract method. If you have two abstract methods then your interface is no longer functional.

If you have one abstract method you can use lambda expressions.

If you see the @FunctionalInterface annotation you know that you shouldn't add any new methods, because it will break design.

If you add new abstract method to any java interface it will break code anyway, because you need to provide implementation to concrete classes

Formulism answered 16/6, 2018 at 22:10 Comment(0)
I
2

The main advantage to protect your interface by @FunctionalInterface is when you use lambda to instantiate them.

Lambda declaration can only declare one block of code so if there is no protection on your interface and some will add an abstract method your lambda have no more sense ...

that why its highly recommend to not implement with lambda some implicit functional interface.

So if you want to implement this interface by lambda way I encourage you to add the annotation that s a security. if you don't want this kind of implementation or if your interface will change or have an night risk to change don t had it.

Inessa answered 16/6, 2018 at 22:13 Comment(1)
The accepted answer completely misses the point of the question. See Ronan's answer instead.Corrincorrina
C
0

Restrict Developer

Yes this @FunctionalInterface annotation to make sure the developer will write only one abstract method in this interface why ? because if there one more abstract class that mean lambda expressions lost it's feature .

Correct Example

@FunctionalInterface
public interface TestFun {
     void test();
}

Incorrect Code

@FunctionalInterface
public interface TestFun {
     void test();
     void m(); // new methods added will lost @FunctionalInterface it's feature 
}

What is the idea ?

let us to use TestFun Interface using lambda expressions .

public class App {

    public static void main(String[] args) {
        TestFun t = () -> {System.out.println("I'm working"); };
    }
}

As we see use the t = ()->{} without telling our code we want to use the void test() directly used, here our idea come if we write two methods like we wrote in the second so we cannot use the lambda expressions in this case we should use @FunctionalInterface to restrict developer use only one abstract method .

And the below code is the real example from Runnable interface and Thread class .

Thread class :

public class Thread implements Runnable {
  *// .......* 
}

Runnable interface :

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}
Charlie answered 10/3, 2021 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.