为什么在 Java 8 中使用@FunctionalInterface 注解

Why to use @FunctionalInterface annotation in Java 8

如果我们有一个只有一个抽象方法的接口,它默认是函数式接口。任何人都可以解释一下@FunctionalInterface 注释带来的额外优势吗?

我知道如果我们添加@FunctionalAnnotation,它不会允许有人在接口中添加另一个抽象方法,因为它会给出一个编译错误,但我的观点是即使你不使用@FunctionalInterface 注解,然后,如果有人要添加另一个抽象方法,它会破坏代码中所有现有的 lambda 表达式,编译器会报错。

例如:

如果我有以下界面:

public interface User {

    Integer fetchData(Integer userId);
}

实施如下:

public class UserImpl implements User{

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

和以下用法:

public class TestFunctionalInterface {

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

}

现在,如果我尝试在界面中添加另一个方法,如下所示:

public interface User {

    Integer fetchData(Integer userId);

    Integer fetchLoginDetails(Integer userId);

}

编译器在以下代码中抱怨:

public class TestFunctionalInterface {

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

}

在用户用户 = a -> a*2;

带有消息“此表达式的目标类型必须是函数式 界面”。

如果不同的模块正在使用该接口,则不会发生编译错误,例如,如果该接口可通过依赖项使用。使用您的模块的人可以安全地在 lambda 中使用该函数,而不必担心以后的更新会破坏他们的代码。

功能接口只能有一个抽象方法。如果您有两个抽象方法,那么您的接口将不再起作用。

如果你有一种抽象方法,你可以使用 lambda 表达式。

如果您看到 @FunctionalInterface 注释,您就知道不应添加任何新方法,因为它会破坏设计。

如果你向任何 java 接口添加新的抽象方法,它无论如何都会破坏代码,因为你需要提供具体的实现 类

通过@functionalInterface 保护您的接口的主要优点是当您使用 lambda 来实例化它们时。

Lambda 声明只能声明一个代码块,所以如果你的接口没有保护,有些人会添加一个抽象方法,你的 lambda 就没有意义了......

这就是为什么强烈建议不要使用 lambda 实现某些隐式函数接口的原因。

因此,如果您想通过 lambda 方式实现此接口,我鼓励您添加安全注解。如果您不想要这种实现,或者如果您的界面将更改或有夜间更改的风险,请不要使用它

限制开发者

是的,这个 @FunctionalInterface 注释可以确保开发人员在此接口中只编写一个抽象方法,为什么?因为如果再有一个抽象 class 就意味着 lambda 表达式 失去了它的特性 .

正确的例子

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

代码不正确

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

想法是什么?

让我们使用 TestFun 使用 lambda 表达式的接口。

public class App {

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

如我们所见,在不告诉代码的情况下使用 t = ()->{} 我们想直接使用 void test(),如果我们像在第二个中那样编写两个方法,那么我们的想法就来了,所以我们不能使用 lambda 表达式 在这种情况下我们应该使用 @FunctionalInterface 来限制开发人员只能使用一种抽象方法。

下面的代码是 Runnable 接口和 Thread class 的真实示例。

Thread class :

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

Runnable界面:

@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();
}