理解 Java 方法引用的基本概念与使用场景
掌握四种方法引用的语法与适用条件
能够将 Lambda 表达式简化为方法引用
熟悉方法引用与函数式接口的配合方式
Java 方法引用是 Java 8 引入的一种语法特性,用于以更简洁的方式引用已存在的方法,而无需实际调用它。它是 Lambda 表达式的进一步简化形式,旨在提升代码的可读性并减少样板代码。方法引用使用双冒号 :: 操作符,并且只能用于函数式接口(即仅包含一个抽象方法的接口)。
关键前提:只有当 Lambda 表达式体中仅调用一个已有方法时,才能使用方法引用进行替换。
引用类的静态方法,使用 类名::静态方法名 的形式。
import java.util.*;
class MathUtil {
static void square(int n) {
System.out.println(n * n);
}
}
class Main {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(2, 3, 4);
list.forEach(MathUtil::square);
}
}输出:
4
9
16等价于 Lambda 表达式:
list.forEach(n -> MathUtil.square(n));适用于工具类中的静态方法(如
Math.abs,Collections.sort等)
引用某个已创建对象的实例方法,使用 对象引用::实例方法名。
import java.util.*;
class Printer {
void print(String msg) {
System.out.println(msg);
}
}
class Main {
public static void main(String[] args) {
Printer printer = new Printer();
List<String> data = Arrays.asList("Java", "Spring", "Boot");
data.forEach(printer::print);
}
}输出:
Java
Spring
Boot等价于:
data.forEach(msg -> printer.print(msg));适用于需要复用某个特定对象行为的场景
引用某类任意实例的实例方法,使用 类名::实例方法名。运行时,该方法会作用于流或集合中的每个元素。
import java.util.*;
class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("java", "spring", "microservice");
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
}输出:
JAVA
SPRING
MICROSERVICE等价于:
names.stream()
.map(name -> name.toUpperCase())
.forEach(s -> System.out.println(s));广泛用于 Stream API 中对元素进行转换、比较等操作(如
String::length,Integer::compareTo)
引用类的构造方法,使用 类名::new,常用于通过函数式接口创建对象。
import java.util.function.Supplier;
class Student {
Student() {
System.out.println("Student object created");
}
}
class Main {
public static void main(String[] args) {
Supplier<Student> supplier = Student::new;
supplier.get(); // 触发构造
}
}输出:
Student object created
等价于:
Supplier<Student> supplier = () -> new Student();常与
Supplier<T>、Function<T,R>等函数式接口配合,实现工厂模式或延迟初始化
方法引用必须与函数式接口配合使用。其核心要求是:
函数式接口的抽象方法签名(参数类型、返回值)必须与被引用方法兼容
常见的函数式接口包括:
Consumer<T>:接收一个参数,无返回(如 System.out::println)
Supplier<T>:无参,有返回(如 LocalDateTime::now)
Function<T, R>:接收一个参数,返回一个结果(如 String::toLowerCase)
Predicate<T>:接收一个参数,返回布尔值(如 String::isEmpty)
应用示例
List<String> fruits = Arrays.asList("Banana", "Apple", "Mango");
// 使用方法引用进行忽略大小写的排序
fruits.sort(String::compareToIgnoreCase);此处 String::compareToIgnoreCase 是一个 (String, String) -> int 类型的方法,恰好匹配 Comparator<String> 接口的 compare 方法签名。
方法引用是 Lambda 表达式的语法糖,用于简化对已有方法的调用
共有四种类型:静态方法、特定对象实例方法、任意对象实例方法、构造器
必须与函数式接口配合使用,且方法签名需匹配
能显著提升代码简洁性和可读性,尤其在 Stream 和集合操作中
不能用于调用多个方法或包含复杂逻辑的场景
为什么 Arrays.asList("a", "b").stream().map(String::new) 这段代码无法编译?请分析原因。
在什么情况下,你更倾向于使用 Lambda 表达式而不是方法引用?举例说明。
尝试将以下 Lambda 表达式改写为方法引用:
list.sort((s1, s2) -> s1.compareTo(s2));