方法引用是对重复调用已有逻辑的精准响应,当Lambda仅转发参数至现有方法时,可用::直接引用,包括静态、实例、类名调用实例和构造器四种形式,提升清晰度与性能,但含计算或副作用的Lambda不应强行替换。
方法引用不是语法糖的装饰,而是对“重复调用已有逻辑”这一常见场景的精准响应。当 Lambda 表达式只做一件事——把参数原样传给某个已存在方法时,它本质上就是冗余的封装。方法引用直接跳过这层包装,用 :: 指向目标方法,让意图更清晰、执行更轻量。
这类 Lambda 有明显特征:体内部没有计算、不新建对象、不改变参数、仅转发调用。比如:
s -> s.toUpperCase() → 可替为 String::toUpperCase
x -> System.out.println(x) → 可替为 System.out::println
() -> new ArrayList<>() → 可替为 ArrayList::new
只要 Lambda 的全部行为都能被一个已有方法完整覆盖,就具备替换条件。
方法引用按调用主体和方法类型分为四类,每种解决一类冗余模式:
立即学习“Java免费学习笔记(深入)”;
ClassName::staticMethod):替代形如 (a, b) -> Math.max(a, b) 的调用,直接写 Math::max
instance::method):当对象已存在且方法需依赖其状态时使用,如 formatter::format 替代 date -> formatter.format(date)
ClassName::method):最常用,用于将参数作为接收者调用方法,如 String::length 等价于 s -> s.length()
ClassName::new):替代 () -> new Xxx() 或 s -> new Xxx(s),避免重复 new 表达式冗余 Lambda 往往散落在各处,导致相同校验、转换或打印逻辑重复出现。改用方法引用后,这些行为自然被牵引到具体方法中:
Validator::nonEmpty,便于统一加日志、监控或启用字符串 internDateUtils::formatAsISO,后续可轻松复用 DateTimeFormatter 实例,避免每次 new若 Lambda 体内含条件判断、多步运算或副作用(如修改状态),强行改成方法引用反而增加复杂度。例如:
s -> s != null ? s.trim() : "" 不适合直接引用,应保留或封装为明确命名的方法再引用obj -> { obj.process(); return obj.getResult(); } 含顺序执行,方法引用无法表达语句块方法引用的价值在于“恰到好处地消除无意义包装”,而不是消灭 Lambda 本身。