Spring注解之@FunctionalInterface详解(函数式接口)
作者:minh_coo
@FunctionalInterface是Java8注解,标识仅含一个抽象方法的函数式接口,支持Lambda,编译检查确保符合定义,提升可读性,非强制,继承方法需注意计数,Object方法不计入
@FunctionalInterface函数式接口
@FunctionalInterface 是Java 8引入的注解,表明一个接口是函数式接口。函数式接口,即只包含一个抽象方法的接口。
目的就是告诉别人,这个接口就一个核心抽象方法,是用来写Lambda 表达式的。
1、函数式接口定义
- 是一个接口;
- 有且仅有一个抽象方法;
- 可以包含任意数量的默认方法(default方法);
- 可以包含任意数量的静态方法(static方法);
- 可以包含从java.lang.Object类继承来的公共方法(如toString(), equals(), hashCode()),这些方法不被计入抽象方法的数量。
如下是一个合格的函数式接口:
@FunctionalInterface
interface ValidFI {
void execute();
boolean equals(Object obj); // 覆盖 Object 的方法,不计入
String toString(); // 覆盖 Object 的方法,不计入
static void helper() {} // 静态方法,允许
default void log() {} // 默认方法,允许
}
2、作用
(1)编译时检查
当给一个接口添加了 @FunctionalInterface 注解时,编译器会强制检查该接口是否严格符合函数式接口的定义(即只有一个抽象方法)。
如果接口不符合条件(例如没有抽象方法、或者有多个抽象方法),编译器会立即报错。这有助于在开发阶段就发现错误,避免运行时出现问题
(2)提升代码可读性,明确意图
在代码中使用 @FunctionalInterface 可以清晰地告诉阅读者:“这个接口是设计用来作为函数式接口使用的,它只有一个核心抽象方法,目的是为了支持 Lambda 表达式或方法引用。”
它提升了代码的可读性和可维护性,是一种良好的文档实践。
注意:
@FunctionalInterface不是强制性的。即使一个接口没有添加@FunctionalInterface注解,只要它事实上只包含一个抽象方法,它仍然是一个函数式接口。Lambda 表达式和方法引用仍然可以用在这个接口上。- 继承的抽象方法会被记入。如果一个接口继承另一个接口,而子接口添加了新的抽象方法,这时在子接口使用
@FunctionalInterface,编译器会报错。 - Object 类方法不计入抽象方法,不影响函数式接口定义。
3、代码示例
// 1. 定义函数式接口
@FunctionalInterface
interface TextTransformer {
// 单一抽象方法 (函数式接口核心)
String transform(String input);
// 默认方法 1
default String transformToUpper(String input) {
return transform(input).toUpperCase();
}
// 默认方法 2
default void printTransformation(String input) {
String result = transform(input);
System.out.println("原始文本: " + input);
System.out.println("转换结果: " + result);
}
// 静态方法 (不影响函数式接口性质)
static void printInfo() {
System.out.println("这是一个文本转换器接口");
}
}
// 2. 传统实现类
class ReverseTransformer implements TextTransformer {
@Override
public String transform(String input) {
return new StringBuilder(input).reverse().toString();
}
}
public class FunctionalInterfaceDemo {
public static void main(String[] args) {
// 3. 使用传统实现类
TextTransformer reverser = new ReverseTransformer();
System.out.println("反转文本: " + reverser.transform("Hello"));
reverser.printTransformation("Java");
System.out.println("大写反转: " + reverser.transformToUpper("World"));
// 调用接口静态方法
TextTransformer.printInfo();
System.out.println("-------------------");
// 4. 使用Lambda表达式实现函数式接口
TextTransformer doubler = input -> input + " " + input;
doubler.printTransformation("Repeat");
System.out.println("大写重复: " + doubler.transformToUpper("Twice"));
System.out.println("-------------------");
// 5. 使用方法引用实现函数式接口
TextTransformer trimmer = String::trim; // 等价于 input -> input.trim()
trimmer.printTransformation(" Trim this text ");
System.out.println("-------------------");
// 6. 作为方法参数传递
processText("Functional", input -> "[" + input + "]");
}
// 方法接受函数式接口作为参数
public static void processText(String text, TextTransformer transformer) {
System.out.println("处理结果: " + transformer.transform(text));
// 使用接口的默认方法
transformer.printTransformation(text);
// 链式调用默认方法
System.out.println("链式转换: " +
transformer.transformToUpper(text).replace("A", "@"));
}
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
