函数式接口是有且仅有一个抽象方法的接口,用于支持Lambda表达式;它不是抽象类,也不能被替代;普通接口可包含其作为参数或返回值,抽象类可持有或调用它但不能取代它。

函数式接口和抽象类、普通接口是不同维度的概念,它们不直接“混用”,但可以协同工作。函数式接口本身是一种特殊的接口,不是抽象类,也不能被抽象类替代。
函数式接口是什么
函数式接口指**有且仅有一个抽象方法**的接口(允许有 default 或 static 方法)。Java 8 引入它主要是为了支持 Lambda 表达式和方法引用。
例如:
-
✅ 正确:`Runnable`(只有一个
run())、`Comparator`(只有一个 compare())、自定义的@FunctionalInterface interface Action { void execute(); } - ❌ 错误:如果接口里有两个抽象方法,哪怕都带 default 实现,也不算函数式接口(编译报错)
抽象类不能作为函数式接口
抽象类天生就不符合函数式接口的定义——它不是接口,不能加 @FunctionalInterface 注解,也不能用 Lambda 直接实例化。
立即学习“Java免费学习笔记(深入)”;
比如下面这段代码会编译失败:
abstract class Printer {
abstract void print(String s);
}
// ❌ 不合法:Lambda 不能用于抽象类
Printer p = s -> System.out.println(s); // 编译错误
原因很直接:Lambda 只能实现函数式接口,不支持抽象类。
接口中使用函数式接口的方式
普通接口可以包含函数式接口类型的字段、参数或返回值,这是常见且推荐的做法。
- 把函数式接口当“行为参数”传入:比如集合的
stream().filter(Predicate)、map(Function) - 在自定义接口中声明函数式接口类型的方法参数:
interface DataProcessor { <T> void process(List<T> data, Function<T, String> formatter); } - 用函数式接口定义回调能力:比如
interface EventHandler { void onEvent(Event e); }(它自己就是函数式接口)
抽象类如何配合函数式接口
抽象类可以持有、接收或调用函数式接口,增强灵活性,但不取代它。
- 作为模板方法的扩展点:抽象类定义流程骨架,把可变部分交给函数式接口
- 例如:
abstract class ReportGenerator { // 模板方法 final void generateReport(List<Data> data) { before(); String content = format(data); // 抽象方法,子类实现 output(content); after(); } // 子类可重写,也可用 Lambda + 函数式接口替代部分逻辑 protected void before() {} protected void after() {} protected abstract String format(List<Data> data); // 额外提供基于函数式接口的便捷入口 public void generateWithFormatter(List<Data> data, Function<List<Data>, String> formatter) { output(formatter.apply(data)); } }


















