Java 8 中使用的功能接口是什么?
What are functional interfaces used for in Java 8?
我在Java8 中遇到了一个新术语:“函数式界面”。在使用 lambda 表达式.
时,我只能找到它的一种用法
Java 8 提供了一些内置的功能接口,如果我们想定义任何功能接口,那么我们可以使用 @FunctionalInterface
注解。它将允许我们在接口中只声明一个方法。
例如:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
除了使用 lambda 表达式外,它在 Java 8 中还有多大用处?
(问题和我问的不一样,问的是为什么我们在使用lambda表达式的时候需要函数式接口。我的问题是:函数式接口除了use with还有什么用处lambda 表达式?)
完全没有。 Lambda 表达式是该注释的唯一点。
@FunctionalInterface
注释对于代码的编译时检查很有用。除了 static
、default
和覆盖 @FunctionalInterface
中 Object
中的方法的抽象方法或用作功能接口的任何其他接口之外,您不能有一个以上的方法。
但是您可以在没有此注释的情况下使用 lambda,也可以在没有 @Override
注释的情况下覆盖方法。
来自文档
a functional interface has exactly one abstract method. Since default
methods have an implementation, they are not abstract. If an interface
declares an abstract method overriding one of the public methods of
java.lang.Object, that also does not count toward the interface's
abstract method count since any implementation of the interface will
have an implementation from java.lang.Object or elsewhere
这个可以在lambda表达式中使用:
public interface Foo {
public void doSomething();
}
这个不能在lambda表达式中使用:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
但这会导致编译错误:
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Invalid '@FunctionalInterface' annotation; Foo is not a functional
interface
lambda 表达式可以分配给功能接口类型,方法引用和匿名也可以 类。
java.util.function
中特定功能接口的一个好处是它们可以组合以创建新功能(如 Function.andThen
和 Function.compose
、Predicate.and
等.) 由于它们包含方便的默认方法。
documentation的目的确实不同
An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification.
和用例
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
其措辞一般不排除其他用例。由于主要目的是指示 功能接口 ,您的实际问题归结为 “ 功能接口是否有其他用例 除了 lambda 表达式和 method/constructor 引用?”
由于功能接口是Java语言规范定义的Java语言结构,只有该规范可以回答这个问题:
JLS §9.8. Functional Interfaces:
…
In addition to the usual process of creating an interface instance by declaring and instantiating a class (§15.9), instances of functional interfaces can be created with method reference expressions and lambda expressions (§15.13, §15.27).
因此 Java 语言规范没有另外说明,该部分中提到的唯一用例是使用方法引用表达式和 lambda 表达式创建接口实例。 (这包括构造函数引用,因为它们在规范中被称为方法引用表达式的一种形式)。
所以一句话,不,Java8 中没有其他用例。
正如其他人所说,功能接口是公开一种方法的接口。它可能有不止一种方法,但所有其他方法都必须有一个默认实现。它被称为 "functional interface" 的原因是因为它有效地充当了一个函数。由于您可以将接口作为参数传递,这意味着函数现在 "first-class citizens" 类似于函数式编程语言。这有很多好处,您会在使用 Stream API 时看到很多好处。当然,lambda 表达式是它们的主要明显用途。
@FunctionalInterface
是与 Java 8 一起发布的新注解,它为 lambda 表达式提供目标类型,并用于代码的编译时检查。
何时使用:
1- 你的接口不能有多个抽象方法,否则会报编译错误
1- 你的接口 应该 是纯的,这意味着功能接口旨在由无状态 类 实现,纯的例子是 Comparator
接口因为它不依赖于实现者的状态,在这种情况下 No 会给出编译错误,但在很多情况下你将无法使用这种接口的 lambda
java.util.function
包包含各种通用功能接口,例如 Predicate
、Consumer
、Function
和 Supplier
。
另请注意,您可以在没有此注释的情况下使用 lambda。
除了其他答案,我认为 "why using Functional Interface other than directly with lambda expressions" 的主要原因可能与面向对象的 Java 语言的性质有关。
Lambda表达式的主要属性有:1. 可以传递 2. 可以在未来的特定时间(多次)执行。现在为了在语言中支持这个特性,其他一些语言只是简单地处理这个问题。
例如在Java脚本中,一个函数(匿名函数,或函数文字)可以作为一个对象来寻址。因此,您可以简单地创建它们,也可以将它们分配给变量等等。例如:
var myFunction = function (...) {
...;
}
alert(myFunction(...));
或者通过 ES6,您可以使用箭头函数。
const myFunction = ... => ...
到目前为止,Java 语言设计者还没有接受通过这些方式(函数式编程技术)来处理上述功能。他们认为 Java 语言是面向对象的,因此他们应该通过面向对象的技术来解决这个问题。他们不想错过 Java 语言的简单性和一致性。
因此,他们使用接口,因为当需要一个只有一种方法(我的意思是功能接口)的接口对象时,您可以将其替换为 lambda 表达式。如:
ActionListener listener = event -> ...;
您可以在 Java 8
中使用 lambda
public static void main(String[] args) {
tentimes(inputPrm - > System.out.println(inputPrm));
//tentimes(System.out::println); // You can also replace lambda with static method reference
}
public static void tentimes(Consumer myFunction) {
for (int i = 0; i < 10; i++)
myFunction.accept("hello");
}
有关 Java Lambdas and FunctionalInterfaces
的更多信息
只有一个抽象方法的接口称为函数式接口。
使用@FunctionalInterface 不是强制性的,但最好将它与功能接口一起使用,以避免意外添加额外的方法。如果接口使用@FunctionalInterface 注解并且我们尝试拥有多个抽象方法,它会抛出编译器错误。
package com.akhi;
@FunctionalInterface
public interface FucnctionalDemo {
void letsDoSomething();
//void letsGo(); //invalid because another abstract method does not allow
public String toString(); // valid because toString from Object
public boolean equals(Object o); //valid
public static int sum(int a,int b) // valid because method static
{
return a+b;
}
public default int sub(int a,int b) //valid because method default
{
return a-b;
}
}
功能接口:
- 介绍于Java8
- 包含 "single abstract" 方法的接口。
示例 1:
interface CalcArea { // --functional interface
double calcArea(double rad);
}
示例 2:
interface CalcGeometry { // --functional interface
double calcArea(double rad);
default double calcPeri(double rad) {
return 0.0;
}
}
示例 3:
interface CalcGeometry { // -- not functional interface
double calcArea(double rad);
double calcPeri(double rad);
}
Java8个注解--@FunctionalInterface
- 注解检查接口是否只包含一个抽象方法。如果不是,则引发错误。
- 即使缺少@FunctionalInterface,它仍然是函数式接口(如果只有一个抽象方法)。注释有助于避免错误。
- 函数式接口可能有额外的静态和默认方法。
- 例如可迭代<>、可比较<>、比较器<>。
函数式接口的应用:
- 方法参考
- Lambda 表达式
- 构造函数引用
学习函数式接口,先学习接口中的默认方法,学习函数式接口后,理解方法引用和lambda表达式会很容易
函数式接口:如果一个接口只有一个抽象方法,则它被称为函数式接口,而不管默认方法或静态方法的数量。函数式接口用于 lamda 表达式。 Runnable
、Callable
、Comparable
、Comparator
是 Functional
接口的几个示例。
主题演讲:
- 使用注释
@FunctionalInterface
(可选)。
- 它应该只有1个抽象方法(不考虑默认和静态的数量
方法)。
- 两个抽象方法给出编译错误(Provider
@FunctionalInterface
annotation is
使用过)。
这篇 thread 更详细地讨论了函数式接口相对于匿名 class 有何好处以及如何使用它们。
我在Java8 中遇到了一个新术语:“函数式界面”。在使用 lambda 表达式.
时,我只能找到它的一种用法Java 8 提供了一些内置的功能接口,如果我们想定义任何功能接口,那么我们可以使用 @FunctionalInterface
注解。它将允许我们在接口中只声明一个方法。
例如:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
除了使用 lambda 表达式外,它在 Java 8 中还有多大用处?
(问题
完全没有。 Lambda 表达式是该注释的唯一点。
@FunctionalInterface
注释对于代码的编译时检查很有用。除了 static
、default
和覆盖 @FunctionalInterface
中 Object
中的方法的抽象方法或用作功能接口的任何其他接口之外,您不能有一个以上的方法。
但是您可以在没有此注释的情况下使用 lambda,也可以在没有 @Override
注释的情况下覆盖方法。
来自文档
a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere
这个可以在lambda表达式中使用:
public interface Foo {
public void doSomething();
}
这个不能在lambda表达式中使用:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
但这会导致编译错误:
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Invalid '@FunctionalInterface' annotation; Foo is not a functional interface
lambda 表达式可以分配给功能接口类型,方法引用和匿名也可以 类。
java.util.function
中特定功能接口的一个好处是它们可以组合以创建新功能(如 Function.andThen
和 Function.compose
、Predicate.and
等.) 由于它们包含方便的默认方法。
documentation的目的确实不同
An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification.
和用例
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
其措辞一般不排除其他用例。由于主要目的是指示 功能接口 ,您的实际问题归结为 “ 功能接口是否有其他用例 除了 lambda 表达式和 method/constructor 引用?”
由于功能接口是Java语言规范定义的Java语言结构,只有该规范可以回答这个问题:
JLS §9.8. Functional Interfaces:
…
In addition to the usual process of creating an interface instance by declaring and instantiating a class (§15.9), instances of functional interfaces can be created with method reference expressions and lambda expressions (§15.13, §15.27).
因此 Java 语言规范没有另外说明,该部分中提到的唯一用例是使用方法引用表达式和 lambda 表达式创建接口实例。 (这包括构造函数引用,因为它们在规范中被称为方法引用表达式的一种形式)。
所以一句话,不,Java8 中没有其他用例。
正如其他人所说,功能接口是公开一种方法的接口。它可能有不止一种方法,但所有其他方法都必须有一个默认实现。它被称为 "functional interface" 的原因是因为它有效地充当了一个函数。由于您可以将接口作为参数传递,这意味着函数现在 "first-class citizens" 类似于函数式编程语言。这有很多好处,您会在使用 Stream API 时看到很多好处。当然,lambda 表达式是它们的主要明显用途。
@FunctionalInterface
是与 Java 8 一起发布的新注解,它为 lambda 表达式提供目标类型,并用于代码的编译时检查。
何时使用:
1- 你的接口不能有多个抽象方法,否则会报编译错误
1- 你的接口 应该 是纯的,这意味着功能接口旨在由无状态 类 实现,纯的例子是 Comparator
接口因为它不依赖于实现者的状态,在这种情况下 No 会给出编译错误,但在很多情况下你将无法使用这种接口的 lambda
java.util.function
包包含各种通用功能接口,例如 Predicate
、Consumer
、Function
和 Supplier
。
另请注意,您可以在没有此注释的情况下使用 lambda。
除了其他答案,我认为 "why using Functional Interface other than directly with lambda expressions" 的主要原因可能与面向对象的 Java 语言的性质有关。
Lambda表达式的主要属性有:1. 可以传递 2. 可以在未来的特定时间(多次)执行。现在为了在语言中支持这个特性,其他一些语言只是简单地处理这个问题。
例如在Java脚本中,一个函数(匿名函数,或函数文字)可以作为一个对象来寻址。因此,您可以简单地创建它们,也可以将它们分配给变量等等。例如:
var myFunction = function (...) {
...;
}
alert(myFunction(...));
或者通过 ES6,您可以使用箭头函数。
const myFunction = ... => ...
到目前为止,Java 语言设计者还没有接受通过这些方式(函数式编程技术)来处理上述功能。他们认为 Java 语言是面向对象的,因此他们应该通过面向对象的技术来解决这个问题。他们不想错过 Java 语言的简单性和一致性。
因此,他们使用接口,因为当需要一个只有一种方法(我的意思是功能接口)的接口对象时,您可以将其替换为 lambda 表达式。如:
ActionListener listener = event -> ...;
您可以在 Java 8
中使用 lambdapublic static void main(String[] args) {
tentimes(inputPrm - > System.out.println(inputPrm));
//tentimes(System.out::println); // You can also replace lambda with static method reference
}
public static void tentimes(Consumer myFunction) {
for (int i = 0; i < 10; i++)
myFunction.accept("hello");
}
有关 Java Lambdas and FunctionalInterfaces
的更多信息只有一个抽象方法的接口称为函数式接口。 使用@FunctionalInterface 不是强制性的,但最好将它与功能接口一起使用,以避免意外添加额外的方法。如果接口使用@FunctionalInterface 注解并且我们尝试拥有多个抽象方法,它会抛出编译器错误。
package com.akhi;
@FunctionalInterface
public interface FucnctionalDemo {
void letsDoSomething();
//void letsGo(); //invalid because another abstract method does not allow
public String toString(); // valid because toString from Object
public boolean equals(Object o); //valid
public static int sum(int a,int b) // valid because method static
{
return a+b;
}
public default int sub(int a,int b) //valid because method default
{
return a-b;
}
}
功能接口:
- 介绍于Java8
- 包含 "single abstract" 方法的接口。
示例 1:
interface CalcArea { // --functional interface
double calcArea(double rad);
}
示例 2:
interface CalcGeometry { // --functional interface
double calcArea(double rad);
default double calcPeri(double rad) {
return 0.0;
}
}
示例 3:
interface CalcGeometry { // -- not functional interface
double calcArea(double rad);
double calcPeri(double rad);
}
Java8个注解--@FunctionalInterface
- 注解检查接口是否只包含一个抽象方法。如果不是,则引发错误。
- 即使缺少@FunctionalInterface,它仍然是函数式接口(如果只有一个抽象方法)。注释有助于避免错误。
- 函数式接口可能有额外的静态和默认方法。
- 例如可迭代<>、可比较<>、比较器<>。
函数式接口的应用:
- 方法参考
- Lambda 表达式
- 构造函数引用
学习函数式接口,先学习接口中的默认方法,学习函数式接口后,理解方法引用和lambda表达式会很容易
函数式接口:如果一个接口只有一个抽象方法,则它被称为函数式接口,而不管默认方法或静态方法的数量。函数式接口用于 lamda 表达式。 Runnable
、Callable
、Comparable
、Comparator
是 Functional
接口的几个示例。
主题演讲:
- 使用注释
@FunctionalInterface
(可选)。 - 它应该只有1个抽象方法(不考虑默认和静态的数量 方法)。
- 两个抽象方法给出编译错误(Provider
@FunctionalInterface
annotation is 使用过)。
这篇 thread 更详细地讨论了函数式接口相对于匿名 class 有何好处以及如何使用它们。