如果我们的接口中只有一个抽象方法,那么它默认是函数式接口。谁能解释一下@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; 行
带有消息“该表达式的目标类型必须是函数 界面”。
如果您有一个抽象方法,则可以使用 lambda 表达式。
如果您看到 @FunctionalInterface 注释,您就知道不应该添加任何新方法,因为它会破坏设计。
如果你向任何java接口添加新的抽象方法,它无论如何都会破坏代码,因为你需要为具体类提供实现
@FunctionalInterface
保护你的接口的主要优点是当你使用 lambda 来实例化它们时。Lambda 声明只能声明一个代码块,所以如果你的接口没有任何保护并且有些人会添加一个抽象方法,那么你的 Lambda 就不再有意义了......
这就是为什么强烈建议不要使用 lambda 实现一些隐式函数接口。
因此,如果您想通过 lambda 方式实现此接口,我鼓励您添加安全性注释。如果你不想要这种实现,或者你的界面会改变或者有夜间改变的风险,那就不要这样做。
@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();
}