为什么在 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();
}
如果我们有一个只有一个抽象方法的接口,它默认是函数式接口。任何人都可以解释一下@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();
}