Java 8 中使用的函数式接口是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36881826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are functional interfaces used for in Java 8?
提问by Madhusudan
I came across a new term in Java 8: "functional interface". I could only find one use of it while working with lambda expressions.
我在 Java 8 中遇到了一个新术语:“函数式接口”。在使用lambda 表达式时,我只能找到它的一种用途。
Java 8 provides some built-in functional interfaces and if we want to define any functional interface then we can make use of the @FunctionalInterface
annotation. It will allow us to declare only a single method in the interface.
Java 8 提供了一些内置的函数式接口,如果我们想定义任何函数式接口,那么我们可以使用@FunctionalInterface
注解。它将允许我们在接口中只声明一个方法。
For example:
例如:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
How useful it is in Java 8 other than just working with lambda expressions?
除了仅使用lambda 表达式之外,它在 Java 8 中有多大用处?
(The question hereis different from the one I asked. It is asking why we need functional interfaces while working with lambda expressions. My question is: why other uses do functional interfaces have besides with lambda expressions?)
(这里的问题与我问的问题不同。它是在问为什么我们在使用 lambda 表达式时需要函数式接口。我的问题是:为什么除了 lambda 表达式之外,函数式接口还有其他用途?)
采纳答案by Sergii Bishyr
@FunctionalInterface
annotation is useful for compilation time checking of your code. You cannot have more than one method besides static
, default
and abstract methods that override methods in Object
in your @FunctionalInterface
or any other interface used as a functional interface.
@FunctionalInterface
注释对于代码的编译时检查很有用。除了和 抽象方法之外static
,您不能有多个default
方法来覆盖Object
您的@FunctionalInterface
或任何其他用作功能接口的接口中的方法。
But you can use lambdas without this annotation as well as you can override methods without @Override
annotation.
但是您可以在没有此注释的情况下使用 lambda,也可以在没有@Override
注释的情况下覆盖方法。
From docs
来自文档
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
一个函数式接口只有一个抽象方法。由于默认方法具有实现,因此它们不是抽象的。如果接口声明了一个抽象方法覆盖了 java.lang.Object 的公共方法之一,这也不会计入接口的抽象方法计数,因为接口的任何实现都将具有来自 java.lang.Object 或其他地方的实现
This can be usedin lambda expression:
这可以在 lambda 表达式中使用:
public interface Foo {
public void doSomething();
}
This cannot be usedin lambda expression:
这不能用于lambda 表达式:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
But this will give compilation error:
但这会产生编译错误:
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Invalid '@FunctionalInterface' annotation; Foo is not a functional interface
'@FunctionalInterface' 注释无效;Foo 不是函数式接口
回答by Louis Wasserman
Not at all. Lambda expressions are the one and only point of that annotation.
一点也不。Lambda 表达式是该注释的唯一要点。
回答by Hank D
A lambda expression can be assigned to a functional interface type, but so can method references, and anonymous classes.
可以将 lambda 表达式分配给函数式接口类型,但方法引用和匿名类也可以。
One nice thing about the specific functional interfaces in java.util.function
is that they can be composed to create new functions (like Function.andThen
and Function.compose
, Predicate.and
, etc.) due to the handy default methods they contain.
关于具体的功能接口的好处之一java.util.function
是,他们可以组合起来创造新的功能(如Function.andThen
和Function.compose
,Predicate.and
等),由于它们所包含的得心应手默认的方法。
回答by Holger
The documentationmakes indeed a difference between the purpose
该文件使得的确目的之间的差异
An informative annotation type used to indicate that an interface type declaration is intended to be a functional interfaceas defined by the Java Language Specification.
用于指示接口类型声明旨在成为Java 语言规范定义的功能接口的信息性注释类型。
and the use case
和用例
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
请注意,可以使用 lambda 表达式、方法引用或构造函数引用创建函数式接口的实例。
whose wording does not preclude other use cases in general. Since the primary purpose is to indicate a functional interface, your actual question boils down to “Are there other use cases forfunctional interfaces other than lambda expressions and method/constructor references?”
其措辞一般不排除其他用例。由于主要目的是指示函数式接口,因此您的实际问题归结为“除了 lambda 表达式和方法/构造函数引用之外,函数式接口还有其他用例吗?”
Since functional interfaceis a Java language construct defined by the Java Language Specification, only that specification can answer that question:
由于函数式接口是 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).
…
除了通过声明和实例化类(第 15.9 节)创建接口实例的通常过程之外,还可以使用方法引用表达式和 lambda 表达式(第 15.13 节、第 15.27 节)创建功能接口的实例。
So the Java Language Specification doesn't say otherwise, the only use case mentioned in that section is that of creating interface instances with method reference expressions and lambda expressions. (This includes constructor references as they are noted as one form of method reference expression in the specification).
因此 Java 语言规范没有另外说明,该部分中提到的唯一用例是使用方法引用表达式和 lambda 表达式创建接口实例。(这包括构造函数引用,因为它们在规范中被称为方法引用表达式的一种形式)。
So in one sentence, no, there is no other use case for it in Java?8.
所以一句话,不,Java 8 中没有其他用例。
回答by Sina Madani
As others have said, a functional interface is an interface which exposes one method. It may have more than one method, but all of the others must have a default implementation. The reason it's called a "functional interface" is because it effectively acts as a function. Since you can pass interfaces as parameters, it means that functions are now "first-class citizens" like in functional programming languages. This has many benefits, and you'll see them quite a lot when using the Stream API. Of course, lambda expressions are the main obvious use for them.
正如其他人所说,功能接口是一个公开一个方法的接口。它可能有多个方法,但所有其他方法都必须有一个默认实现。它被称为“函数式接口”的原因是因为它有效地充当了一个函数。由于您可以将接口作为参数传递,这意味着函数现在是“一等公民”,就像在函数式编程语言中一样。这有很多好处,在使用 Stream API 时,您会看到很多好处。当然,lambda 表达式是它们的主要明显用途。
回答by Ahmad Al-Kurdi
@FunctionalInterface
is a new annotation are released with Java 8 and provide target types for lambda expressions and it used on compilation time checking of your code.
@FunctionalInterface
是 Java 8 中发布的新注解,为 lambda 表达式提供目标类型,并用于代码的编译时检查。
When you want to use it :
当你想使用它时:
1- Your interface must nothave more than one abstract methods, otherwise compilation error will be given.
1- 你的接口不能有一个以上的抽象方法,否则会出现编译错误。
1- Your interface Shouldbe pure, which means functional interface is intended to be implemented by stateless classes, exmple of pure is Comparator
interface because its not depend on the implementers state, in this case Nocompilation error will be given, but in many cases you will not be able to use lambda with this kind of interfaces
1- 你的接口应该是纯的,这意味着功能接口是由无状态类实现的,纯Comparator
接口的例子是因为它不依赖于实现者的状态,在这种情况下不会给出编译错误,但在很多情况下你将无法在这种接口中使用 lambda
The java.util.function
package contains various general purpose functional interfaces such as Predicate
, Consumer
, Function
, and Supplier
.
所述java.util.function
包中包含各种通用功能的接口,如Predicate
,Consumer
,Function
,和Supplier
。
Also please note that you can use lambdas without this annotation.
另请注意,您可以在没有此注释的情况下使用 lambda。
回答by MMKarami
Beside other answers, I think the main reason to "why using Functional Interface other than directly with lambda expressions" can be related to nature of Java language which is Object Oriented.
除了其他答案之外,我认为“为什么使用函数式接口而不是直接使用 lambda 表达式”的主要原因可能与面向对象的 Java 语言的性质有关。
The main attributes of Lambda expressions are: 1. They can be passed around 2. and they can executed in future in specific time (several times). Now to support this feature in languages, some other languages deal simply with this matter.
Lambda 表达式的主要属性是: 1. 可以左右传递 2. 将来可以在特定时间(多次)执行。现在为了在语言中支持这个特性,其他一些语言只是简单地处理这个问题。
For instance in Java Script, a function (Anonymous function, or Function literals) can be addressed as a object. So, you can create them simply and also they can be assigned to a variable and so forth. For example:
例如,在 Java Script 中,一个函数(匿名函数,或函数文字)可以作为一个对象来寻址。因此,您可以简单地创建它们,也可以将它们分配给变量等等。例如:
var myFunction = function (...) {
...;
}
alert(myFunction(...));
or via ES6, you can use an arrow function.
或者通过 ES6,你可以使用箭头函数。
const myFunction = ... => ...
Up to now, Java language designers have not accepted to handle mentioned features via these manner (functional programming techniques). They believe that Java language is Object Oriented and therefore they should solve this problem via Object Oriented techniques. They don't want to miss simplicity and consistency of Java language.
到目前为止,Java 语言设计者还没有接受通过这些方式(函数式编程技术)来处理提到的特性。他们认为 Java 语言是面向对象的,因此他们应该通过面向对象的技术来解决这个问题。他们不想错过 Java 语言的简单性和一致性。
Therefore, they use interfaces, as when an object of an interface with just one method (I mean functional interface) is need you can replace it with a lambda expression. Such as:
因此,它们使用接口,因为当需要只有一种方法(我的意思是函数式接口)的接口对象时,您可以将其替换为 lambda 表达式。如:
ActionListener listener = event -> ...;
回答by Websterix
You can use lambda in Java 8
您可以在 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");
}
For further info about Java Lambdasand FunctionalInterfaces
回答by Akhilesh
An interface with only one abstract method is called Functional Interface. It is not mandatory to use @FunctionalInterface, but it's best practice to use it with functional interfaces to avoid addition of extra methods accidentally. If the interface is annotated with @FunctionalInterface annotation and we try to have more than one abstract method, it throws compiler error.
只有一个抽象方法的接口称为功能接口。使用@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;
}
}
回答by Ketan
Functional Interface:
功能接口:
- Introduced in Java 8
- Interface that contains a "single abstract" method.
- 在 Java 8 中引入
- 包含“单一抽象”方法的接口。
Example 1:
示例 1:
interface CalcArea { // --functional interface
double calcArea(double rad);
}
Example 2:
示例 2:
interface CalcGeometry { // --functional interface
double calcArea(double rad);
default double calcPeri(double rad) {
return 0.0;
}
}
Example 3:
示例 3:
interface CalcGeometry { // -- not functional interface
double calcArea(double rad);
double calcPeri(double rad);
}
Java8 annotation -- @FunctionalInterface
Java8注解—— @FunctionalInterface
- Annotation check that interface contains only one abstract method. If not, raise error.
- Even though @FunctionalInterface missing, it is still functional interface (if having single abstract method). The annotation helps avoid mistakes.
- Functional interface may have additional static & default methods.
- e.g. Iterable<>, Comparable<>, Comparator<>.
- 注解检查接口只包含一个抽象方法。如果不是,则引发错误。
- 即使缺少@FunctionalInterface,它仍然是功能接口(如果有单个抽象方法)。注释有助于避免错误。
- 函数式接口可能有额外的静态和默认方法。
- 例如 Iterable<>、Comparable<>、Comparator<>。
Applications of Functional Interface:
函数式接口的应用:
- Method references
- Lambda Expression
- Constructor references
- 方法参考
- Lambda 表达式
- 构造函数引用
To learn functional interfaces, learn first default methods in interface, and after learning functional interface, it will be easy to you to understand method reference and lambda expression
学习函数式接口,首先学习接口中的默认方法,学习了函数式接口之后,你会很容易理解方法引用和lambda表达式