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

问题描述 投票:0回答:4

如果我们的接口中只有一个抽象方法,那么它默认是函数式接口。谁能解释一下@FunctionalInterface注释带来了什么额外的好处?

我知道如果我们添加@FunctionalAnnotation,它将不允许有人在接口中添加另一个抽象方法,因为它会给出编译错误,但我的观点是即使你不使用@FucntionalInterface注释,那么也,如果有人添加另一个抽象方法,它将破坏代码中所有现有的 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));
    }

}

在 User user = a -> a*2; 行

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

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


8
投票
函数式接口只能有一个抽象方法。如果你有两个抽象方法,那么你的接口就不再起作用了。

如果您有一个抽象方法,则可以使用 lambda 表达式。

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

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


2
投票
通过

@FunctionalInterface

 保护你的接口的主要优点是当你使用 lambda 来实例化它们时。

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

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

因此,如果您想通过 lambda 方式实现此接口,我鼓励您添加安全性注释。如果你不想要这种实现,或者你的界面会改变或者有夜间改变的风险,那就不要这样做。


0
投票
限制开发者

是的,这个

@FunctionalInterface

注释可以确保开发人员在此接口中只编写一个抽象方法,为什么?因为如果还有一个抽象类意味着 
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
 类的真实示例。

Thread

班级:

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(); }
    
© www.soinside.com 2019 - 2024. All rights reserved.