157. Java Lambda 表达式 - 绑定方法引用:让对象方法调用更优雅
在 Java 的方法引用中,绑定方法引用(bound method reference) 是一种特殊形式,它引用的是特定对象的实例方法。这种引用方式比传统的 Lambda 表达式更简洁、清晰,特别适合简化一些对固定对象的重复操作。
1. 什么是绑定方法引用?
绑定方法引用 表示方法引用已经绑定到一个具体对象上。调用该方法时,不需要再传入这个对象,它已经"内置"到方法引用中。
✅ 语法形式:
java
object::instanceMethod
其中 object
是某个实例,instanceMethod
是这个对象的方法名。
2. 示例:使用 System.out.println
作为绑定方法引用
先来看一个最常见的例子,把字符串打印到控制台:
使用 Lambda 表达式:
java
Consumer<String> printer = s -> System.out.println(s);
使用绑定方法引用:
java
Consumer<String> printer = System.out::println;
System.out::println
是绑定方法引用,它等价于上面的 Lambda 表达式。它表示"对 System.out
对象调用 println
方法"。
3. 示例:绑定到自定义对象的方法
来看一个自定义类的例子:
java
public class User {
private String name;
public User(String name) { this.name = name; }
public String getName() { return name; }
}
使用 Lambda 表达式:
java
User yaoxin = new User("Anna");
Supplier<String> yname = () -> yaoxin.getName();
System.out.println(yname.get()); // 输出 "Anna"
使用绑定方法引用:
java
User yaoxin = new User("Anna");
Supplier<String> yname = yaoxin::getName;
System.out.println(yname.get()); // 输出 "Anna"
🔍 说明:
yaoxin::getName
是绑定方法引用。Supplier<String>
接口的get()
方法会直接调用yaoxin.getName()
。
4. 区分绑定方法引用与未绑定方法引用
类型 | 示例 | 是否已绑定对象 | 接口类型示例 | 等价 Lambda |
---|---|---|---|---|
✅ 绑定方法引用 | yaoxin::getName |
✅ 是 | Supplier<String> |
() -> yaoxin.getName() |
❌ 未绑定方法引用 | User::getName |
❌ 否 | Function<User, String> |
user -> user.getName() |
5. 常见使用场景
- ✅ 固定对象的方法调用:如日志输出、界面组件更新等。
- ✅ JavaBean Getter 简化 :如
user::getName
可绑定用于某个 UI 控件、日志组件等。 - ✅ 流式 API 中的简写 :与
Stream
、Optional
等组合使用,提升可读性。
6. 小练习
✅ 判断下面哪个是绑定方法引用?哪个是未绑定方法引用?
练习 1:
java
Function<User, String> f = User::getName;
- ✅ 未绑定方法引用 。调用时仍需传入
User
对象。
练习 2:
java
User u = new User("Tom");
Supplier<String> s = u::getName;
- ✅ 绑定方法引用 。对象
u
已在方法引用中确定。
练习 3:
java
Function<Integer, Integer> increment = x -> x + 1;
这个 Lambda 表达式无法使用方法引用简化为绑定形式,因为没有一个已有方法可以完成这个逻辑。
⚠️ 错误示例(不符合接口签名):
java
Function<Integer, Integer> increment = Integer::sum; // ❌ 错误,需要两个参数
正确示例
java
BiFunction<Integer, Integer, Integer> adder = Integer::sum;
✅ 总结
- 绑定方法引用 :指向一个具体对象的实例方法,语法为
object::method
,适用于Supplier
、Consumer
等接口。 - 它和 未绑定方法引用 (
ClassName::method
)不同,后者调用时仍需传入对象。 - 绑定方法引用常用于固定对象的回调逻辑或方法委托,使代码更加简洁优雅。