Java 中的函数式接口

2025年4月21日 | 阅读 8 分钟

只包含一个抽象方法的接口被称为函数式接口。它可以包含任意数量的默认方法和静态方法,但只能包含一个抽象方法。它也可以声明对象类的方法。

Java 以其多功能性和广泛接受度而闻名,并逐渐发展以适应现代编程范式。近年来的一项重大变化是函数式编程,其灵感来自 Scala、Haskell 和 Clojure 等语言。函数式架构引入了一种不同的软件开发方法,它以使用不可变函数和数据结构作为一等公民为基础。这种转变通过 Java 中用户界面的引入而得到促进。

什么是函数式接口?

Java 中的函数式接口是只包含一个抽象方法的接口。传统的描述性约定接口实现了类,而函数式接口则侧重于行为,允许开发人员将任务视为对象。它们构成了 Java 编程特性的基石,支持使用 Lambda 语法和风格。

函数式接口也称为单一抽象方法接口或 SAM 接口。它是 Java 中的一项新特性,有助于实现函数式编程方法。

Java 8 中引入函数式接口是游戏规则的改变者,它为开发人员提供了更简洁、更透明的代码编写方式。这些交互为在 Java 生态系统中采用设计策略铺平了道路。

示例

输出

Hello there

函数式接口可以拥有对象类的方法。让我们通过以下示例来理解它。

示例

输出

Hello there

无效的函数式接口

函数式接口只有在不包含任何抽象方法的情况下才能扩展另一个接口。

示例

输出

compile-time error

示例 3

在下面的示例中,函数式接口正在扩展一个非函数式接口。

示例

输出

Hello there
Do it now

Lambda 表达式和方法引用

函数式接口与 Lambda 表达式和方法引用结合使用时会大放异彩。Lambda 表达式提供了定义匿名函数的简洁语法,而方法引用允许开发人员通过名称引用现有方法。

将 Lambda 表达式与 Predicate 结合使用

通过利用 Lambda 表达式和方法引用,开发人员可以编写更具表现力、更易于理解和维护的代码。这些特性使 Java 中的编程风格更具函数式,促进了不可变数据和纯函数的使用。

Java 预定义函数式接口

Java 8 在 java.util.function 包中引入了几个内置的函数式接口,每个接口都旨在支持常见的函数式编程模式。一些最常用的函数式接口包括

Supplier: 表示结果的供应商。

Consumer: 表示接受单个输入参数且不返回任何结果的操作。

Predicate: 表示一个参数的谓词(布尔值函数)。

Function: 表示接受一个参数并产生结果的函数。

UnaryOperator: 表示对单个操作数执行操作并产生与其操作数相同类型结果的操作。

BinaryOperator: 表示对两个相同类型操作数执行操作,并产生与操作数相同类型结果的操作。

这些函数式接口为在 Java 中编写函数式风格的代码提供了基础。它们封装了常见模式,使开发人员能够编写更简洁、更易读的代码。

自定义函数式接口

Java 提供了许多函数式接口,开发人员甚至可以根据自己的特定需求定义自己的函数式接口。这种灵活性允许根据特定应用程序的需求定制特定领域的函数式接口。

通过使用 @FunctionalInterface 注解接口,开发人员表明它旨在用作函数式接口。此注解是可选的,但作为文档工具,使接口的意图对其他开发人员清晰可见。

我们还可以定义自己的自定义函数式接口。以下是属于 java.util.function 包的函数式接口列表。

Interface描述
BiConsumer<T,U>它表示接受两个输入参数且不返回任何结果的操作。
Consumer<T>它表示接受单个参数且不返回任何结果的操作。
Function<T,R>它表示接受一个参数并返回结果的函数。
Predicate<T>它表示一个参数的谓词(布尔值函数)。
BiFunction<T,U,R>它表示接受两个参数并返回结果的函数。
BinaryOperator<T>它表示对两个相同数据类型操作数执行操作。它返回与操作数相同类型的结果。
BiPredicate<T,U>它表示两个参数的谓词(布尔值函数)。
BooleanSupplier它表示布尔值结果的供应商。
DoubleBinaryOperator它表示对两个 double 类型操作数执行操作并返回 double 类型值。
DoubleConsumer它表示接受单个 double 类型参数且不返回任何结果的操作。
DoubleFunction<R>它表示接受 double 类型参数并产生结果的函数。
DoublePredicate它表示一个 double 类型参数的谓词(布尔值函数)。
DoubleSupplier它表示 double 类型结果的供应商。
DoubleToIntFunction它表示接受 double 类型参数并产生 int 类型结果的函数。
DoubleToLongFunction它表示接受 double 类型参数并产生 long 类型结果的函数。
DoubleUnaryOperator它表示对单个 double 类型操作数执行操作并产生 double 类型结果。
IntBinaryOperator它表示对两个 int 类型操作数执行操作并返回 int 类型结果。
IntConsumer它表示接受单个整数参数且不返回任何结果的操作。
IntFunction<R>它表示接受整数参数并返回结果的函数。
IntPredicate它表示一个整数参数的谓词(布尔值函数)。
IntSupplier它表示整数类型的供应商。
IntToDoubleFunction它表示接受整数参数并返回 double 值的函数。
IntToLongFunction它表示接受整数参数并返回 long 值的函数。
IntUnaryOperator它表示对单个整数操作数执行操作并产生整数结果。
LongBinaryOperator它表示对两个 long 类型操作数执行操作并返回 long 类型结果。
LongConsumer它表示接受单个 long 类型参数且不返回任何结果的操作。
LongFunction<R>它表示接受 long 类型参数并返回结果的函数。
LongPredicate它表示一个 long 类型参数的谓词(布尔值函数)。
LongSupplier它表示 long 类型结果的供应商。
LongToDoubleFunction它表示接受 long 类型参数并返回 double 类型结果的函数。
LongToIntFunction它表示接受 long 类型参数并返回整数结果的函数。
LongUnaryOperator它表示对单个 long 类型操作数执行操作并返回 long 类型结果。
ObjDoubleConsumer<T>它表示接受一个对象和一个 double 参数且不返回任何结果的操作。
ObjIntConsumer<T>它表示接受一个对象和一个整数参数的操作。它不返回结果。
ObjLongConsumer<T>它表示接受一个对象和一个 long 参数且不返回任何结果的操作。
Supplier<T>它表示结果的供应商。
ToDoubleBiFunction<T,U>它表示接受两个参数并产生 double 类型结果的函数。
ToDoubleFunction<T>它表示返回 double 类型结果的函数。
ToIntBiFunction<T,U>它表示接受两个参数并返回整数的函数。
ToIntFunction<T>它表示返回整数的函数。
ToLongBiFunction<T,U>它表示接受两个参数并返回 long 类型结果的函数。
ToLongFunction<T>它表示返回 long 类型结果的函数。
UnaryOperator<T>它表示对单个操作数执行操作并返回与其操作数相同类型结果的操作。

结论

函数式接口改变了 Java 开发人员的编程方式,使他们能够在语言中采用编程风格,为 Lambda 语法和风格提供了基础。函数式接口使开发人员能够编写简洁、透明且可维护的代码。

随着 Java 的不断发展,编程很可能在语言的未来发挥越来越重要的作用。通过有效利用业务接口和拥抱编程原则,开发人员可以开辟新的可能性并创建健壮且可扩展的软件系统。


Java 8 函数式接口选择题

1. Java 中用于表示函数式接口的以下哪个注解?

  1. @FunctionalInterface
  2. @Functional
  3. @Interface
  4. @Func
 

答案:A

解释: @FunctionalInterface 注解用于表示 Java 中的函数式接口。它确保接口只包含一个抽象方法。


2. Java 中函数式接口的目的是什么?

  1. 为类提供多个抽象方法以供实现。
  2. 为实现它的类定义契约。
  3. 启用 Lambda 表达式和方法引用的使用。
  4. 强制封装和数据隐藏。
 

答案:C

解释: 函数式接口支持使用 Lambda 表达式和方法引用,提供了一种简洁的方式来实现单一抽象方法接口。


3. Java 的 java.util.function 包中哪个函数式接口表示接受两个参数并产生结果的函数?

  1. Consumer
  2. 函数
  3. BiFunction
  4. Supplier
 

答案:C

解释: Java 的 java.util.function 包中的 BiFunction 接口表示接受两个参数并产生结果的函数。


4. Java 中哪个函数式接口表示接受一个参数并产生相同类型结果的函数?

  1. UnaryOperator
  2. BinaryOperator
  3. 函数
  4. 谓词
 

答案:A

解释: Java 中的 UnaryOperator 接口表示接受一个参数并产生相同类型结果的函数。


5. Java 中方法引用的目的是什么?

  1. 提供一种引用方法而不调用它们的方式。
  2. 为接口中的方法指定默认实现。
  3. 封装行为以用于 Lambda 表达式。
  4. 允许同时在不同线程中调用方法。
 

答案:A

解释: Java 中的方法引用提供了一种引用方法而不直接调用它们的方式,当 Lambda 表达式只是简单地调用现有方法时,它为 Lambda 表达式提供了一种简洁的语法。


下一主题Java 8 Stream