方法引用是lambda的等价替代,需满足函数式接口、已有方法、签名完全一致三条件;按调用主体分静态、特定对象、任意对象实例、构造四类;常见坑包括空指针、泛型擦除、参数顺序错。

方法引用不是语法糖,是 Lambda 的等价替代——但只在“调用已有方法”时成立。硬核通关的关键,不是记住四种写法,而是能一眼判断:能不能用、该用哪一种、为什么这里会报错。
先盯死三个硬性条件
方法引用能用的前提,缺一不可:
- 目标位置必须是函数式接口(只有一个抽象方法,比如 Consumer、Function、Comparator)
- 被引用的方法必须已存在,不能是临时写的逻辑
- 被引用方法的参数个数、类型、返回值,必须和函数式接口抽象方法的签名完全一致
四类引用怎么选,看调用主体是谁
别背格式,按“谁在调这个方法”来区分:
-
静态方法引用(Class::staticMethod):方法属于类,不依赖对象。比如
Integer::parseInt、String::valueOf -
特定对象的实例方法引用(obj::instanceMethod):方法属于某个已经创建好的对象。比如
list::add、formatter::format -
任意对象的实例方法引用(Class::instanceMethod):方法属于某类,但调用者由接口参数传入。比如
String::toLowerCase(等价于s -> s.toLowerCase()),String::compareTo -
构造方法引用(Class::new):用来创建对象。比如
ArrayList::new对应Supplier<arraylist></arraylist>,HashMap::new可匹配Function<integer hashmap></integer>
常见翻车点,全是细节坑
面试官最爱在这里卡人:
-
空指针静默炸:用
obj::toString,但 obj 是 null?运行时报NullPointerException,不是编译错 -
泛型擦除导致不匹配:比如
List<string>.stream().map(String::length)</string>没问题,但若泛型是自定义类且重写了equals却没配hashCode,可能在collect(toSet())时行为异常 -
参数顺序搞反:
Comparator的compare(a,b)是 a-b,但String::compareTo是a.compareTo(b),所以String::compareTo可直接用;换成Integer::compareTo就不行——因为Integer的compareTo是this.compareTo(other),而Comparator<integer></integer>要求第一个参数是调用者,刚好匹配
练出直觉:看到代码秒反应
遇到这类写法,立刻心算签名是否对得上:
-
System.out::println→ 接口是Consumer<t></t>,println(T)参数一个、无返回,✓ -
Arrays::sort→ 错!sort有多个重载,没有单参数T[]且无返回的版本,不能直接引用 -
LocalDateTime::now→ 接口是Supplier<localdatetime></localdatetime>,now()无参、返回LocalDateTime,✓ -
user::getName→ 若user是局部变量且所在方法已结束,闭包里保存的是原始引用,后续执行可能 NPE
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











