深入解析 Java 方法引用:Lambda 表达式的进化之路
前言
方法引用是 Java 8 提供的一种新特性,它允许我们更简洁地传递现有方法作为参数。这项特性实际上是对 Lambda 表达式的一种补充,通过方法引用,我们可以直接引用现有方法,而无需编写完整的Lambda表达式。最近在使用方法引用的过程中有了一些感悟,这里希望以文章的形式记录下来,与大家分享。

1. 背景
最近在使用 Mybatis-plus 这个框架,这个框架能在 Mybatis 的基础上减少简单 SQL 的编写,直接使用Java 代码的方式拼接我们想要的 SQL,我为了研究怎样才能不写 SQL 也是在尽量多地翻看 Mybatis-plus 相关文档,尽量能用代码解决地绝不写 SQL。

1.1. LambdaQueryMapper
LambdaQueryMapper 是 MyBatis-Plus 提供的一种基于 Lambda 表达式的查询方式。通过使用 LambdaQueryMapper,我们可以利用 Lambda 表达式来编写类型安全的、更具可读性的查询代码,而无需担心手动编写 SQL 或者处理字符串连接等操作。下面是一个查询示例:
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryWrapper;public class UserService {private UserMapper userMapper;// 查询用户列表的方法示例public List<User> queryUserList(String username, Integer age, String email) {LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();// 构建查询条件queryWrapper.eq(User::getUsername, username).gt(age != null, User::getAge, age).like(email != null, User::getEmail, email);// 执行查询List<User> userList = userMapper.selectList(queryWrapper);return userList;}
}
在这个查询示例中,我们可以通过 User::getAge 指定 age 字段为查询条件,通过 User::getEmail来指定 email 为查询条件。这种形式的 Java 代码就叫做方法引用。
1.2. 函数式接口
说到方法引用,就不得不说函数式接口。在 java 中只有一个抽象方法的接口叫做函数式接口,每一种方法引用类型实际上对应一个函数式接口。
例如我们比较熟悉的 Runnable ,它其实就是一个函数式接口。它的定义如下:
@FunctionalInterface
public interface Runnable {public abstract void run();
}
它就代表可以接收一个没有参数也没有返回值的方法:
public class Test {public static void main(String[] args) {Test test = new Test();test.runnable(test::getXxx);}public void runnable(Runnable runnable){runnable.run();}public void getXxx(){System.out.println("run");}
}
同样的,如果我希望接收只有一个参数且只有一个返回值的方法进来,怎么做呢?Java 中也提供了这样的函数式接口 Function<T,R>:
@FunctionalInterface
public interface Function<T, R> {R apply(T t);
}
它接收一个参数 T,且返回一个类型 R,所以我们就可以这么用
public class Test {public static void main(String[] args) {Test test = new Test();test.function(test::getXyy);}public <T,R> void function(Function<T,R> function){}public Integer getXyy(String s){return 1;}
}
1.3. 对于 User::getAge 疑惑
通过上面的叙述,我们知道只要在方法中声明函数式接口,我们就可以使用方法引用的形式将函数作为方法参数传入方法中。但是我在查看 LambdaQueryWrapper 源码的过程中方法,它在 eq、like 等方法中定义的参数类型为函数是接口是 SFunction<T,R>
@FunctionalInterface
public interface SFunction<T, R> extends Function<T, R>, Serializable {
}
也就是说它本质也是一个 Function<T,R> ,匹配的是一个参数以及一个返回值的方法,但是 User::getAge对应的 get 方法只有返回值而没有参数,这是怎么匹配上的?

2. 理解
经过一番查找资料,我终于理解了。下面就由小的来解释一下其中的原由。方法引用我们可以将其分成两部分,以 User::getAge 为例,前半部分是 User,它既可以是 User 类,也可以是 User 对象。后半部分是 getAge 它既可以是类方法(静态方法)也可以是对象方法(非静态方法),理论上有四种组合,即:
- 对象-类方法
- 对象-对象方法
- 类-类方法
- 类-对象方法
2.1. 对象::类方法
这种形式是不被允许的,会直接报错:

2.2. 对象::对象方法
如果是这种,其实就是直接匹配,也就是说,方法的类型必须和方法引用对应,以 Function<T,R> 为例,必须得是一个参数和一个返回值,代码如下:
public class Test {public static void main(String[] args) {Test test = new Test();//引用为对象test.function(test::getXyy);}public <T,R> void function(Function<T,R> function){}public Integer getXyy(String s){return 1;}
}
2.3. 类::类方法
这种和上面是一样的,也是要遵循参数和返回值相对应的规则:
public class Test {public static void main(String[] args) {Test test = new Test();//引用变为类test.function(Test::getXyy);}public <T,R> void function(Function<T,R> function){}/*** 变为静态方法*/public static Integer getXyy(String s){return 1;}
}
2.4. 类::对象方法
而对于类::对象方法这种形式,它就有点特殊了,它存在一个隐式转换,我们先看代码:
public class Test {public static void main(String[] args) {Test test = new Test();test.function(Test::getXyy);}public <T,R> void function(Function<T,R> function){}/*** 无参数、一个返回值的对象方法*/public Integer getXyy(){return 1;}
}
function 期待的参数类型是:一个参数、一个返回值的方法,然而对应的却是:无参数、一个返回值的方法,这是怎么回事呢?
原来,对于这种类型的方法引用存在一个隐式转化,即:Test::getXyy 等价于 (Test t) -> t.getXyy(),而 (Test t) -> t.getXyy()代表的就是:一个参数,一个返回值的方法,所以才能匹配 Function<T,R>函数式接口类型。
为什么它需要做这样的转换?本质上是由于类是无法调用对象方法,所以对于 类::对象方法这种形式的方法引用都需要进行这样的隐式转换。
相关文章:
深入解析 Java 方法引用:Lambda 表达式的进化之路
前言 方法引用是 Java 8 提供的一种新特性,它允许我们更简洁地传递现有方法作为参数。这项特性实际上是对 Lambda 表达式的一种补充,通过方法引用,我们可以直接引用现有方法,而无需编写完整的Lambda表达式。最近在使用方法引用的…...
MySQL作业 (3)多表查询
多表查询 1.创建student和score表2.为student表和score表增加记录3.查询student表的所有记录4.查询student表的第2条到4条记录5.从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息6.…...
ConcurrentHashMap和HashMap的区别
什么是HashMap (1)HashMap 是基于 Map 接口的非同步实现,线程不安全,是为了快速存取而设计的;它采用 key-value 键值对的形式存放元素(并封装成 Node 对象),允许使用 null 键和 nul…...
MCM备赛笔记——图论模型
Key Concept 图论是数学的一个分支,专注于研究图的性质和图之间的关系。在图论中,图是由顶点(或节点)以及连接这些顶点的边(或弧)组成的。图论的模型广泛应用于计算机科学、通信网络、社会网络、生物信息学…...
算法笔记(动态规划入门题)
1.找零钱 int coinChange(int* coins, int coinsSize, int amount) {int dp[amount 1];memset(dp,-1,sizeof(dp));dp[0] 0;for (int i 1; i < amount; i)for (int j 0; j < coinsSize; j)if (coins[j] < i && dp[i - coins[j]] ! -1)if (dp[i] -1 || dp[…...
开发实践_阶段三
编写一个告知APP。 需求: 1.登录、注册 2.发布定向讯息:检测是否登录,是则向用户或用户组发布 ”名称 时间“ ;否则提示登录 3.讯息接收:检测是否登录,是则查看收到信息(未读数)…...
codegeex和通义灵码辅助编程——以及通义灵码无法登陆的bug解决
通义的速度更快,延迟低,150ms。 codegeex速度慢些,延迟较高,500ms。 个人评价:延迟低的会很好地改善使用体验,所以通义加分。 但是整体功能上还是codegeex强一些,可以选中代码进行对话…...
Android14之DefaultKeyedVector实现(一百八十二)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...
银河麒麟操作系统 v10 中离线安装 Docker
银河麒麟操作系统 v10 中离线安装 Docker 1. 查看系统版本2. 查看 Linux 内核版本(3.10以上)3. 查看 iptabls 版本(1.4以上)4. 判断处理器架构5. 离线下载 Docker 安装包6. 移动解压出来的二进制文件到 /usr/bin 目录中7. 配置 Do…...
如何系统的学习Python
学习 Python 的时候,可以按照以下步骤进行系统学习: 学习 Python 基础知识:首先了解 Python 的基础语法、数据类型、变量和运算符等基本概念。可以通过阅读《Python编程从入门到实践》等经典教材来建立基础。也可以通过翻阅Python官方文档来进…...
Java并发基础:一文讲清util.concurrent包的作用
java.util.concurrent包是 Java 中用于并发编程的重要工具集,提供了线程池、原子变量、并发集合、同步工具类、阻塞队列等一系列高级并发工具类,使用这些工具类可以极大地简化并发编程的难度,减少出错的可能性,提高程序的效率和可…...
C++PythonC# 三语言OpenCV从零开发(2):教程选择
文章目录 相关专栏前言视频教学和官方文档视频教程OpenCV 官方教程最终选择我的最终选择 相关专栏 C&Python&Csharp in OpenCV 前言 OpenCV 有官方的教程和简单的视频教程: OpenCV 官方教程 B站也有相关的视频教学 OpenCV4 C 快速入门视频30讲 - 系列合集 …...
【嘉立创EDA-PCB设计指南】3.网络表概念解读+板框绘制
前言:本文对网络表概念解读板框绘制(确定PCB板子轮廓) 网络表概念解读 在本专栏的上一篇文章【嘉立创EDA-PCB设计指南】2,将设计的原理图转为了PCB,在PCB界面下出现了所有的封装,以及所有的飞线属性&…...
nodejs前端项目的CI/CD实现(二)jenkins的容器化部署
一、背景 docker安装jenkins,可能你会反问,这太简单了,有什么好讲的。 我最近就接手了一个打包项目,它是一个nodejs的前端项目,jenkins已在容器里部署且运行OK。 但是,前端组很追求新技术,不…...
python爬虫案例分享
当然,我可以分享一个基本的Python爬虫示例。这个示例将使用Python的requests库来抓取网页内容,然后使用BeautifulSoup库来解析和提取信息。我们将构建一个简单的爬虫来从一个示例网站抓取标题。 Python爬虫示例 目标 提取某网站的标题。 需要的库 r…...
【CC++】为什么 scanf 函数在读取字符串时不需要用取地址运算符
在C语言中如何使用 scanf 读取字符串 在C语言中,字符串实际上是字符数组,所以我们可以使用scanf函数来读取字符串。但是,需要注意的是,scanf在读取字符串时会在遇到空格、制表符或换行符时停止。因此,它不能用于读取包…...
Linux dirs命令教程:dirs命令详解与实例(附实例详解和注意事项)
Linux dirs命令介绍 dirs这是一个内置在shell中的命令,用于显示当前被记忆的目录列表。默认状态下,它会按照stack的方式储存目录,即最后加入的目录会被首先列出来。 Linux dirs命令适用的Linux版本 dirs命令在所有常见的Linux发行版中都适…...
掌握虚拟化:PVE平台安装教程与技术解析
🌟🌌 欢迎来到知识与创意的殿堂 — 远见阁小民的世界!🚀 🌟🧭 在这里,我们一起探索技术的奥秘,一起在知识的海洋中遨游。 🌟🧭 在这里,每个错误都…...
Godot FileDialog无法访问其它盘符的文件
问题描述 使用Godot的FileDialog对象访问Windows系统的文件,例如: func _on_hud_sig_save():var dlg FileDialog.new()dlg.set_access(FileDialog.ACCESS_FILESYSTEM)dlg.set_file_mode(FileDialog.FILE_MODE_SAVE_FILE)add_child(dlg)dlg.popup_cent…...
TestNG注释
目录 TestNG注释列表 BeforeXXX和AfterXXX注释放在超类上时如何工作? 使用BeforeXXX和AfterXXX TestNG注释 TestNG是一个测试框架,旨在简化广泛的测试需求,从单元测试(隔离测试一个类)到集成测试(测试由…...
图解人工智能(31)深度学习前沿
在词向量模型中,训练的目的是使相关的词离的更近,不相关的词离的更远,其中“相关性”是按语义上的远近来判断的。假设我们要对下列领域中的对象做嵌入,该如何定义对象的相关性?(1)动物园里的动物…...
图片去水印怎样快速搞定?2026年实测去水印工具推荐与方法全解
去水印是许多内容创作者和日常用户都会遇到的需求。无论是保存喜欢的图片、重新编辑素材,还是处理自己的作品,都需要用到高效的去水印方法。本文将为你详细介绍2026年最实用的图片去水印工具和操作方法,帮助你快速找到适合自己的解决方案。 小…...
qb-web测试策略:Jest单元测试与Vue组件测试最佳实践
qb-web测试策略:Jest单元测试与Vue组件测试最佳实践 【免费下载链接】qb-web A qBittorrent Web UI, write in TypeScriptVue. 项目地址: https://gitcode.com/gh_mirrors/qb/qb-web qb-web作为基于TypeScriptVue开发的qBittorrent Web UI,采用Je…...
算法实例分析:使数组相等的最小开销
使数组相等的最小开销通过题意分析可知要让所有值相等,必然不需要超出数据的最大最小值,因此左右边界可以预先缩小范围。然后根据我们上面的分析不断缩小搜索边界范围。关于函数的计算,只要统计所有数据与的差值再乘上权重即可。最后注意&…...
太顶了!输入主题,这几款AI论文软件自动生成毕业论文初稿!
毕业季论文焦虑?还在为选题、查资料、写大纲、润色修改熬夜到凌晨?别担心,现在只需输入主题,几款AI论文工具就能自动生成图文并茂的毕业论文初稿,从开题到定稿全流程搞定!千笔AI、ThouPen、豆包、DeepSeek、…...
论云原生层次架构在自动驾驶云控平台中的应用
【摘要】2024年3月,我作为核心系统架构师,主导了某新能源车企“新一代自动驾驶云控与数据平台”的重构与研发工作。该平台主要负责接入现役50万辆在线车辆,处理海量的多模态工况数据,并支撑大规模自动驾驶算法的并行仿真与实时监控…...
【Spring】 AOP 核心原理,与声明式事务传播机制
一、什么是 AOPAOP(Aspect Oriented Programming,面向切面编程)核心思想在不修改原有业务代码的情况下,对方法进行统一增强。例如:日志记录;权限校验;事务管理;性能统计;…...
ElevenLabs台湾话语音上线后用户留存率骤降47%?揭秘方言语料清洗盲区与3步合规性校验法
更多请点击: https://intelliparadigm.com 第一章:ElevenLabs台湾话语音上线后用户留存率骤降47%?揭秘方言语料清洗盲区与3步合规性校验法 ElevenLabs于2024年Q2正式上线台湾话(闽南语)语音合成服务,初期D…...
4.0修复版去水印小程序源码 内含去水印免费接口
内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 流量主变现:集成微信广告,支持开屏 / 激励 / Banner 广告,直接盈利。 前后端能力: 前端:3 套 UI 可选,改版后功能完…...
夜色 galgame官方正版2026最新版pc免费下载(看到请立即转存 资源随时失效)手机版通用
下载链接、 解压密码:WWW.FZGAMER.COM 《夜色》(Muse:Night Out):基于图像解密与非对称博弈的独立派对游戏解析 在第一人称射击、硬核动作或竞技音游占据主流市场的当下,专注于“非对称信息传递”与“图像…...
