方法引用分三类:静态方法引用(如integer::parseint)、构造方法引用(如person::new)、实例方法引用(如string::tolowercase),核心是参数与返回值类型严格匹配,实现简洁复用。

直接用 :: 操作符引用工具类的静态方法,就能跳过 Lambda 冗余写法,把已有逻辑“拎出来”即插即用。关键不是“能不能用”,而是“参数和返回值是否对得上”——匹配了,一行代码就完成行为传递。
静态方法引用:最常用、最直白的复用方式
工具类(比如 Math、Integer、Objects、自定义的 StringUtils)里的静态方法,天然适合被引用。只要函数式接口的抽象方法签名和该静态方法一致,就能无缝替换。
-
参数数量、顺序、类型必须完全一致:例如
Function<string integer></string>接口的apply(T)方法接收一个String,返回Integer,那Integer::parseInt就刚好匹配;但Long::parseLong就不行(返回类型是Long) -
自动拆装箱可用,但别依赖隐式转换:如
Comparator.comparingInt(Math::abs)能工作,是因为int abs(int)和Integer参数能自动拆箱,但若工具方法是abs(long),编译就会报错 -
避免在引用中夹带逻辑:像
s -> s.trim().length()不能直接用方法引用替代,因为涉及两个操作;但如果已有StringUtils.lengthAfterTrim(String),就可以写成StringUtils::lengthAfterTrim
构造方法引用:快速生成对象,尤其配合 Stream.collect
当需要反复创建同类对象(比如封装结果、构建 DTO),用 ClassName::new 比写 () -> new Xxx() 更干净,也更利于后续统一管理构造逻辑。
- 无参构造:
Supplier<list>> listGen = ArrayList::new</list> - 单参构造(如
Person(String name)):Function<string person> personFactory = Person::new</string>,调用时personFactory.apply("Alice") - 多参或复杂构造建议封装为静态工厂方法,再用静态方法引用,保持引用体简洁
实例方法引用(特定对象):绑定上下文,固化配置
如果工具逻辑依赖某个已初始化的对象(比如带格式的 DateTimeFormatter、预设规则的 DecimalFormat),直接引用它的实例方法,就把格式、精度、区域等上下文“冻结”进函数里。
- 例如:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");,之后可写Function<localdate string> printer = fmt::format</localdate> - 这种引用本质是“闭包轻量版”——不暴露内部状态,只暴露行为,线程安全且复用稳定
- 注意:该对象生命周期需长于引用使用周期,避免
NullPointerException
任意对象的实例方法引用:让类型自己“动起来”
这是把“方法归属权”交还给数据本身,特别适合字符串处理、集合操作等泛型场景。语法是 ClassName::methodName,编译器会自动把第一个参数当作调用者。
- 典型例子:
String::toLowerCase对应Function<string string></string>;List::isEmpty对应Predicate<list></list> - 排序中高频使用:
list.sort(String::compareToIgnoreCase)等价于(s1,s2) -> s1.compareToIgnoreCase(s2) - 限制:被引用的方法不能是
static,且第一个参数类型必须是该类本身(或其父类/接口)











