背景
在练习方法引用的时候,突然想到一个问题,方法引用是什么时候用那?用在哪里那?刚开始以为只是用在lambda出现的地方,后来查询了下,任何使用函数对象的地方,都可以使用,下面是查询的回答,在此做个记录。
查询结果
在Java中,方法引用(Method References)是一种简洁的方式,用来直接引用已经存在的方法,而不是通过Lambda表达式来定义匿名函数。方法引用可以用于任何接受函数式接口作为参数的地方,而不仅仅是Lambda表达式的上下文。函数式接口是指只有一个抽象方法的接口。
方法引用的四种形式
- 静态方法引用:
ClassName::staticMethod - 特定对象的实例方法引用:
instance::instanceMethod - 任意对象的实例方法引用:
Type::instanceMethod - 构造方法引用:
ClassName::new
使用场景
-
Stream API:这是最常见使用方法引用的场景之一。当你需要对流中的元素执行某种操作时,如果这个操作正好对应于一个已有的方法,那么你可以使用方法引用来代替Lambda表达式。
List<String> strings = Arrays.asList("apple", "banana", "orange"); strings.stream().map(String::toUpperCase).forEach(System.out::println); -
事件处理:在GUI编程中,如使用Swing或JavaFX时,可以将方法引用用于事件处理器。
button.setOnAction(event -> System.out.println("Button clicked!")); // 可以用方法引用替代: button.setOnAction(this::handleButtonClick); -
多线程编程:当创建新线程并指定其运行的任务时,如果任务是一个已有方法,可以直接使用方法引用。
new Thread(new Runnable() { @Override public void run() { doTask(); } }).start(); // 可以用方法引用替代: new Thread(this::doTask).start(); -
Comparator:当你需要创建比较器时,方法引用也可以简化代码。
List<Person> people = ...; people.sort(Comparator.comparing(Person::getName)); -
工厂模式:当你有一个工厂方法用于创建对象实例时,可以使用构造方法引用。
Supplier<MyClass> supplier = MyClass::new; MyClass instance = supplier.get();
Lambda表达式与方法引用
方法引用实际上是Lambda表达式的一种更简洁的形式。如果你发现你的Lambda表达式只是简单地调用了一个方法,那么通常可以将其替换为方法引用。例如:
// Lambda 表达式
strings.forEach(s -> System.out.println(s));
// 方法引用
strings.forEach(System.out::println);
两者是等价的,但方法引用更加简洁,并且有时可读性更好。不过,只有当Lambda表达式体仅包含一个方法调用时,才能用方法引用来替换它。如果Lambda表达式包含了更多的逻辑,比如条件判断、循环等,则不能使用方法引用。
总结
方法引用可以在任何接受函数式接口作为参数的地方使用,这包括但不限于Lambda表达式的上下文。它们提供了一种更简洁、更易读的方式来引用现有方法,尤其是在你只需要执行一个方法调用的情况下。