为何SelectDSLCompleter无抽象方法却可作为Java函数式接口正常工作?
你提到的SelectDSLCompleter能正常作为函数式接口使用,核心原因是它继承了java.util.function.Function接口,而Function本身已经定义了唯一的抽象方法,完全符合Java函数式接口的要求。
函数式接口的本质要求
Java中函数式接口的定义是:包含且仅包含一个抽象方法的接口,但这个抽象方法可以来自父接口,不需要当前接口自己显式定义。只要整个接口的抽象方法总数(包括继承而来的)为1,就可以标注@FunctionalInterface并作为函数式接口使用。
具体到SelectDSLCompleter的分析
SelectDSLCompleter继承了Function<QueryExpressionDSL<SelectModel>, Buildable<SelectModel>>,而Function接口的核心抽象方法是:
R apply(T t);
这里的泛型参数已经被具体化为:
- 输入参数类型:
QueryExpressionDSL<SelectModel> - 返回值类型:
Buildable<SelectModel>
而SelectDSLCompleter自身只定义了两个静态方法(allRows()和allRowsOrderedBy()),静态方法不属于抽象方法范畴,不会影响接口的抽象方法计数。所以整个接口的抽象方法数量仍然是1,完全满足函数式接口的要求。
结合使用示例验证
在Service的调用代码中:
List<Person> allRecords = mapper.select(c -> c);
这里的c -> c是一个lambda表达式,它实现的正是从Function继承来的apply方法——接收一个QueryExpressionDSL<SelectModel>类型的参数c,直接返回该参数(符合Buildable<SelectModel>的返回要求)。
再看接口中的静态方法,比如allRows():
static SelectDSLCompleter allRows(){ return (c) -> { return c; }; }
这里返回的lambda同样是实现了apply方法,和上面的调用逻辑完全一致。
内容的提问来源于stack exchange,提问作者赵震宇

