作为一种面向对象的编程语言, Java 不可能有独立的函数,因为除了一些原始数据类型和方法之外,所有的东西都围绕着类和对象。函数一直是类的一部分,只能使用对象或类来调用。
然而,随着Java8的发布,一个叫做函数接口的新概念以及其他一些功能如 Lambda表达式 、时间API、流API等被发布。
但是,这些函数接口是什么,你如何定义它们?让我们来了解一下!
什么是接口?
接口作为一种抽象机制,规定了一个类的行为。它也被称为一个包含抽象方法和静态常量的类的蓝图。一个接口可以包含一个或多个抽象方法,而不是方法主体。
简单地说,一个接口就像一个合同,每个实现类都必须遵守。比如说。

因此,如果实现该接口的类没有声明该接口的所有方法,代码将无法运行并抛出一个错误:“error: A1 is not abstract and does not override an abstract method in A1”。
在JDK8之前,接口不能定义实现,但现在可以为接口方法添加默认实现。我们还可以定义静态和默认方法,这些方法可以在没有接口中的对象的情况下被调用。
基本上,接口是用来实现代码中的 多重继承 和松散 耦合 的。
现在我们对接口有了清楚的了解,让我们看看什么是函数接口,以及它是如何工作的。
什么是函数接口?
函数接口也被称为单一抽象方法(SAM)接口,因为它不能有多于一个抽象方法。
函数接口可以有多个静态和缺省方法,并有一个实现和一个额外的抽象方法。为了将一个接口标记为函数接口,@FunctionalInterface注解被用来避免错误地声明额外的方法。
函数接口之所以如此受欢迎,是因为它为 程序员 提供了使用Lambda表达式来实例化接口的能力,而无需使用匿名和庞大的类实现。
此外,在函数接口中使用抽象关键字是可选的,因为定义在接口内的方法默认是抽象的。
但是,Lambda表达式是什么意思?
Lambda表达式是一种未命名的或匿名的方法,它不单独执行,而是用来实现函数接口的定义方法。它被定义为

使用的箭头运算符(->)被称为λ运算符。例如,如果我们有一个方法,如下所示。

使用Lambda表达式,它可以写成:
我们可以看到,Lambda函数中的方法没有任何参数,使得 运算符 的左边是空的。而右侧定义了动作,在本例中,它将返回Golden Radio的值:1.61803。
在Java8之前,实现接口或创建内类对象是至关重要的,但随着Java8的引入,我们所能做的就是将Lambda表达式分配给功能接口。
功能接口实例

要创建功能接口,你可以使用@FunctionalInterface注解或使用Java预定义的功能接口。
例子A:
- 首先,我们将标记@FunctionalInterface,并创建一个名为MyInterface的接口,其抽象方法名为getGoldenRationValue()。
- 然后我们将创建一个名为main的公有类来执行这个方法。
- 为了在功能接口中使用lambda表达式,我们将声明一个对MyInterfaceDemo的引用,然后将lambda表达式分配给该引用。
- 最后,我们将使用引用接口打印出黄金分割率的值。
Value of Golden Ratio = 1.61803
例B:

- 在这个例子中,我们将使用一个预定义的函数接口ToDouble Function ,它接收一个参数T并返回一个双倍数作为输出。
- ToDoubleFuntion包含一个抽象的方法,名为applyasDouble()。
- 最后,我们将打印包括空格在内的信息长度。
预定义函数接口列表
现在我们知道了如何定义函数接口,让我们看看有多少个预定义的功能接口。
主要有四种类型的功能接口,即Consumer、Predicate、Function和Supplier,人们可以在不同情况下实现它们。在这四个接口中,Consumer、Function和Predicate有额外的功能接口。
下面是Java中所有内置或预定义的接口的列表。
注意:下表中提到的T、U和R分别代表第一个参数、第二个参数和操作结果的类型。
Interface |
Type |
Runnable |
→ |
BiConsumer(T, U) |
T, U → |
BiFunction(T, U, R) |
T, U → R |
Binary Operator |
T, T → R |
BiPredicate<T, U> |
T, U → Boolean |
BooleanSupplier |
→ boolean |
Consumer |
T → |
DoubleBinaryOperator |
double, double → double |
DoubleConsumer |
double → |
DoubleFunction |
double → R |
DoublePredicate |
double → boolean |
DoubleSupplier |
boolean → |
DoubleToIntFunction |
double → int |
DoubleToLongFunction |
double → long |
DoubleUnaryOperator |
double → double |
Function<T, R> |
T → R |
Int BinaryOperator |
int → int |
IntConsumer |
int → |
IntFunction |
int → R |
IntPredicate |
int → boolean |
IntSupplier |
→ int |
IntToDoubleFunction |
int → double |
IntToLongFunction |
int → long |
IntUnaryOperator |
int → int |
LongBinaryOperator |
long, Long → long |
LongConsumer |
long → |
LongFunction |
long → R |
LongPredicate |
long → boolean |
LongSupplier |
→ long |
LongToDoubleFunction |
long → double |
LongToIntFunction |
long → int |
LongUnaryOperator |
long → long |
ObjDoubleConsumer |
T, double → |
ObjIntConsumer |
T, int → |
ObjLongConsumer |
T, long → |
Predicate |
T → boolean |
Supplier |
→ T |
ToDoubleBiFunction<T, U> |
T, U → double |
ToDoubleFunction |
T → double |
ToIntBiFunction<T, U> |
T, U → int |
ToIntFunction |
T → int |
ToLongBiFunction<T, U> |
T, U → long |
ToLongFunction |
T → long |
UnaryOperator |
T → T |
总结
一个接口作为一种抽象机制。
函数接口可以有多个静态和默认的方法,并有一个实现和一个额外的抽象方法。
在函数接口内定义的方法默认是抽象的,因此,现在使用抽象关键字是可选的。
Lambda表达式是一个匿名的方法,它不会自己执行,而是用来实现函数接口的定义方法。
要创建函数接口,你可以使用@FunctionalInterface注解或使用Java预定义的函数接口。
以上就是关于函数接口的全部内容,我们希望它能帮助你理解基础知识。请记住,我们只是触及了函数接口的表面,你还可以从Java中的每个预定义的函数接口中了解更多。