方法引用是当已有对象的某方法签名匹配函数式接口时最直接的调用方式,分“对象::实例方法”“类名::实例方法”“对象::方法”三类,适用于签名完全匹配且无复杂逻辑的场景,核心价值在于语义显性化而非语法简化。

方法引用不是炫技工具,而是当你已经有一个现成对象、且它的某个方法恰好匹配函数式接口签名时,最直接的“拿来就用”方式。关键不在语法多酷,而在是否省去冗余包装、让意图一目了然。
用 对象::实例方法 直接绑定已有实例
当你手头已有一个具体对象(比如一个 hero 实例),又需要把它某个无参或单参方法作为回调传入(如 forEach、Supplier、Consumer),就不用再写 x -> obj.doSomething(x) 这类包裹。
- 正确场景:对象已存在,方法签名与目标函数式接口兼容
- 常见误用:把
String::length当作Predicate<string></string>用——错,因为length()返回int,不返回boolean;它适合ToIntFunction<string></string>或Supplier<integer></integer>(当绑定到具体字符串时) - 实用例子:
String str = "hello";
Supplierlen = str::length; // 调用 str.length(),无参数,返回 int
System.out.println(len.get()); // 输出 5
用 类名::实例方法 表达“对每个元素调用它的某方法”
这不是调用某个固定对象的方法,而是告诉编译器:“等会儿流里每个元素,都当作这个方法的调用者”。它对应的是双参数函数式接口(如 BiFunction、Comparator)或接受单个参数并隐式调用其方法的接口(如 Function<t></t>)。
- 典型用法:
String::toUpperCase→Function<string string></string>,因为"abc".toUpperCase()接收当前字符串,返回新字符串 - 排序场景:
list.sort(String::compareTo)等价于(a, b) -> a.compareTo(b),第一个参数自动作为调用者 - 注意:不能写
list.forEach(String::print)——String没有静态或实例print方法;但可以写System.out::println,因为那是PrintStream的实例方法
用 对象::方法 配合自定义工具类做条件过滤
当你的判断逻辑封装在某个工具类的实例方法中,而该方法签名符合 Predicate、Function 等接口时,直接复用比写 Lambda 更清晰。
- 例如:
new StringUtil()::judge,前提是judge(String s)返回boolean,就能直接用于filter - 优势:业务语义外移,主流程不掺杂判断细节;测试也更容易——只需单独测
StringUtil.judge - 限制:该工具类实例必须在引用作用域内可访问(不能是局部变量且未 final 或 effectively final)
避免强行套用:方法引用不是万能缩写
它只适用于“方法签名完全匹配 + 行为即调用”的简单场景。一旦涉及组合、判空、默认值、异常处理或多个步骤,就该果断退回 Lambda。
- ❌ 不要写:
list.stream().map(s -> s != null ? s.trim() : "")并试图改成方法引用——没对应方法 - ✅ 改成:
list.stream().map(s -> s == null ? "" : s.trim()),保持可读性 - 记住:方法引用的价值是“语义显性化”,不是字符数最少。写出来让人一眼看懂“这里就是调 xx 对象的 yy 方法”,才算用对了

















