函数式接口
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 39 课,共 87 课。
函数式接口是只包含一个抽象方法的接口。这个单方法限制让函数式接口很特别,因为你可以用 lambda 表达式实现它们,从而编写更简洁的代码。
Java 提供了 @FunctionalInterface 注解,用于明确标记一个接口为函数式接口。虽然这是可选的,但如果你不小心添加了第二个抽象方法,这个注解可以帮助编译器发现错误:
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}你可以用传统方式通过类实现函数式接口,也可以用 lambda 表达式更简洁地实现:
// 传统实现方式
Calculator adder = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda 表达式(简短多了!)
Calculator adder = (a, b) -> a + b;
System.out.println(adder.calculate(5, 3)); // 8函数式接口仍然可以包含默认方法和静态方法,因为这些方法不计入单个抽象方法的规则。Java 的 java.util.function 包提供了许多内置的函数式接口,例如 Predicate、Function 和 Consumer。在使用流和集合时,你会经常遇到它们。
挑战
简单让我们使用函数式接口和 lambda 表达式来构建一个字符串转换系统。你将创建一个灵活的文本处理器,它可以对字符串应用不同的转换操作,而这一切都由一个函数式接口驱动。
你将把代码分成三个文件:
StringTransformer.java:定义一个表示任意字符串转换操作的函数式接口。使用@FunctionalInterface注解标记它,确保它保持函数式接口的特性。你的接口应声明一个名为transform的抽象方法,该方法接收一个 String 并返回一个 String。TextProcessor.java:创建一个使用函数式接口处理文本的类。它应有一个用于保存StringTransformer的字段,以及一个用于初始化该字段的构造函数。添加一个名为process(String text)的方法,用转换器处理给定文本并返回结果。通过这种设计,你可以在构造函数中传入任意转换行为。Main.java:使用 lambda 表达式创建不同的转换操作,将所有内容组合起来。你将接收两个输入:一个文本字符串和一个操作类型(upper、lower或reverse)。根据操作类型,使用相应的 lambda 创建一个
TextProcessor:upper:将文本转换为大写lower:将文本转换为小写reverse:反转文本(提示:使用StringBuilder)
然后,使用输入文本调用
process(),并按以下格式打印结果:Result: [transformed text]
你将接收两个输入:要转换的文本(String)和操作类型(String)。
注意,同一个 TextProcessor 类可以根据传入的 lambda 执行完全不同的操作,这就是函数式接口的强大之处!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine();
String operation = scanner.nextLine();
TextProcessor processor;
// TODO:根据操作类型,用合适的 lambda 创建一个 TextProcessor:
// “upper”:将文本转换为大写
// “lower”:将文本转换为小写
// “reverse”:反转文本(提示:使用 StringBuilder)
// TODO:用输入文本调用 process(),并打印结果
// 输出格式:“Result: [transformed text]”
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器