函数式接口是只声明一个抽象方法的接口,可用@functionalinterface标注以明确意图并启用编译检查;可含多个default或static方法,但抽象方法仅能有一个,lambda和方法引用依赖于此特性。

Java 自定义函数式接口,核心是定义一个且仅有一个抽象方法的接口,并用 @FunctionalInterface 显式标注——它不是必须的,但强烈建议加上,既能明确意图,又能让编译器帮你检查是否意外添加了第二个抽象方法。
什么是函数式接口?
函数式接口(Functional Interface)指**只声明了一个抽象方法**的接口。它可以有多个 default 方法或 static 方法,但抽象方法只能有一个。Lambda 表达式、方法引用等函数式编程特性,都依赖于这类接口。
-
Runnable、Comparator、Function<t></t>都是 JDK 自带的典型函数式接口 - 自定义时,只要满足“单抽象方法”规则,就可作为函数式接口使用
-
@FunctionalInterface是标记性注解,不改变行为,但加了它,编译器会报错提醒你:别多写抽象方法
怎么写一个自定义函数式接口?
以“判断字符串是否满足某条件”为例,定义一个类似 Predicate<string></string> 的接口:
@FunctionalInterface
public interface StringChecker {
boolean test(String s); // 唯一抽象方法
// 可以有 default 方法(不影响函数式接口性质)
default StringChecker and(StringChecker other) {
return s -> this.test(s) && other.test(s);
}
// 也可以有 static 方法
static StringChecker not(StringChecker checker) {
return s -> !checker.test(s);
}
}
- 接口名建议体现用途(如
StringChecker、IntCalculator),避免泛泛叫MyFunc - 抽象方法命名可参考 JDK 惯例:
apply(转换)、test(判断)、accept(消费)、get(获取) - 参数和返回值类型按需设计,支持泛型(如
<t> boolean test(T t)</t>)
@FunctionalInterface 的作用和常见误区
这个注解主要起两个作用:一是语义清晰,告诉其他开发者“这是用来写 Lambda 的”;二是编译期校验。
- 如果加了
@FunctionalInterface却不小心写了两个抽象方法,编译直接失败,比如:boolean test(String s);void log(String s);→ 编译报错:“Unexpected @FunctionalInterface annotation” - 不加
@FunctionalInterface也能当函数式接口用(只要满足单抽象方法),但失去编译保护,容易出错 - 注意:Object 类的 public 方法(如
toString()、equals()、hashCode())不算抽象方法,不会破坏函数式接口性质
怎么用自定义函数式接口?
写完接口后,就能像用 JDK 内置接口一样,配合 Lambda 或方法引用使用:
// 使用 Lambda
StringChecker isEmpty = s -> s == null || s.trim().isEmpty();
System.out.println(isEmpty.test("")); // true
// 使用方法引用
StringChecker isBlank = String::isBlank;
// 组合使用(得益于 default/static 方法)
StringChecker nonEmptyNotBlank = isEmpty.and(isBlank).negate(); // 假设已定义 negate
- Lambda 体里写逻辑,类型由接口方法签名自动推断
- 可结合 default 方法实现链式组合(如 and/or/negate),提升复用性
- 适合封装领域特定行为,比如校验规则、计算策略、回调逻辑等
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











