Java 1.8 函数式接口 Functional Interface

更新时间 2023-05-30 08:42:31

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书活动

目前, 星球 内第一个项目:全栈前后端分离博客项目,演示地址:http://116.62.199.48/, 1.0 版本已经更新完毕,正在更新 2.0 版本。采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 224 小节,累计 35w+ 字,讲解图:1544 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 1000+ 小伙伴加入,欢迎点击围观

先抛出一个疑问:在我们书写一段 Lambda 表达式后(比如上一章节 中匿名内部类的 Lambda 表达式缩写形式),Java 编译器是如何进行类型推断的,它又是怎么知道重写的哪个方法的?

需要说明的是,不是每个接口都可以缩写成 Lambda 表达式。只有那些函数式接口(Functional Interface)才能缩写成 Lambda 表示式。

那么什么是函数式接口(Functional Interface)呢?

所谓函数式接口(Functional Interface)就是只包含一个抽象方法的声明。针对该接口类型的所有 Lambda 表达式都会与这个抽象方法匹配。

注意:你可能会有疑问,Java 8 中不是允许通过 defualt 关键字来为接口添加默认方法 吗?那它算不算抽象方法呢?答案是:不算。因此,你可以毫无顾忌的添加默认方法,它并不违反函数式接口(Functional Interface)的定义。

总结一下:只要接口中仅仅包含一个抽象方法,我们就可以将其改写为 Lambda 表达式。为了保证一个接口明确的被定义为一个函数式接口(Functional Interface),我们需要为该接口添加注解:@FunctionalInterface。这样,一旦你添加了第二个抽象方法,编译器会立刻抛出错误提示。

示例代码:

@FunctionalInterface
interface Converter<F, T> {
    T convert(F from);
}

示例代码2:

Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

注意:上面的示例代码,即使去掉 @FunctionalInterface 也是好使的,它仅仅是一种约束而已。