为啥在 Java 8 中使用 @FunctionalInterface 注解
Posted
技术标签:
【中文标题】为啥在 Java 8 中使用 @FunctionalInterface 注解【英文标题】:Why to use @FunctionalInterface annotation in Java 8为什么在 Java 8 中使用 @FunctionalInterface 注解 【发布时间】:2018-06-16 22:00:39 【问题描述】:如果我们的接口中只有一个抽象方法,则默认为函数式接口。谁能解释一下@FunctionalInterface注解带来了什么额外的好处?
我知道如果我们添加@FunctionalAnnotation,它将不允许有人在接口中添加另一个抽象方法,因为它会给出编译错误,但我的观点是即使你不使用@FucntionalInterface注解,那么另外,如果有人添加另一个抽象方法,它会破坏代码中所有现有的 lambda 表达式,编译器会报错。
例如:
如果我有以下接口:
public interface User
Integer fetchData(Integer userId);
具有以下实现:
public class UserImpl implements User
@Override
public Integer fetchData(Integer userId)
return 1;
及以下用法:
公共类 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。它也可用作文档。并且某些 SAM 接口不旨在定义为 lambda 表达式。见***.com/questions/28166187/… @JB Nizet,感谢您的回复。如果我的编译单元中没有任何 lambda,即使在这种情况下,如果我在接口中添加另一个抽象方法,我应该很确保所有要实现这个接口的类都会失败,因为它们需要实现这个新方法。 除非您在编译单元中没有此接口的任何具体实现。您可能会编写一个库,定义一个接口,但不自己实现它。同样,它还用于记录该接口被设计为实现为 lambda 表达式。 What is use of Functional Interface in Java 8?的可能重复 【参考方案1】:功能接口只能有一个抽象方法。如果你有两个抽象方法,那么你的接口就不再起作用了。
如果您有一种抽象方法,则可以使用 lambda 表达式。
如果您看到 @FunctionalInterface 注释,您就知道不应添加任何新方法,因为它会破坏设计。
如果你向任何 java 接口添加新的抽象方法,它无论如何都会破坏代码,因为你需要为具体类提供实现
【讨论】:
【参考方案2】:如果不同的模块正在使用该接口,则不会发生编译错误,例如,如果该接口通过依赖项可用。使用您的模块的人可以安全地在 lambda 中使用该函数,而不必担心以后的更新会破坏他们的代码。
【讨论】:
【参考方案3】:@functionalInterface 保护接口的主要优点是当你使用 lambda 实例化它们时。
Lambda 声明只能声明一个代码块,所以如果你的接口没有保护,有些人会添加一个抽象方法,你的 lambda 就没有更多意义了......
这就是为什么强烈建议不要使用 lambda 实现一些隐式函数接口。
因此,如果您想通过 lambda 方式实现此接口,我鼓励您添加作为安全性的注释。如果你不想要这种实现,或者你的界面会改变或者有改变的风险,那就不要了
【讨论】:
【参考方案4】:限制开发者
是的,这个@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();
【讨论】:
以上是关于为啥在 Java 8 中使用 @FunctionalInterface 注解的主要内容,如果未能解决你的问题,请参考以下文章