#方法引用类型
面试官问:"Java 有哪几种方法引用?"
候选人小秦答:"静态方法引用和实例方法引用。"
面试官追问:"还有呢?"
小秦说:"...好像还有构造器引用?"
面试官追问:"四种方法引用的区别是什么?"
小秦答不上来。
【面试官心理】 方法引用是 Lambda 表达式的简化形式。能说出四种方法引用并能正确使用的候选人,说明对函数式编程有实际经验。
#一、四种方法引用 🔴
| 类型 | 语法 | 示例 | 相当于 |
|---|---|---|---|
| 静态方法引用 | ClassName::staticMethod | Integer::parseInt | x -> Integer.parseInt(x) |
| 实例方法引用(特定对象) | object::instanceMethod | str::length | () -> str.length() |
| 实例方法引用(任意对象) | ClassName::instanceMethod | String::length | s -> s.length() |
| 构造器引用 | ClassName::new | ArrayList::new | () -> new ArrayList() |
#二、静态方法引用 🔴
// Lambda 形式
Function<String, Integer> parser = s -> Integer.parseInt(s);
// 方法引用形式
Function<String, Integer> parser = Integer::parseInt;
// 使用
parser.apply("123"); // 123#三、实例方法引用(特定对象)🔴
// Lambda 形式
String str = "hello";
Supplier<Integer> len = () -> str.length();
// 方法引用形式
Supplier<Integer> len = str::length;
// 使用
len.get(); // 5#四、实例方法引用(任意对象)🔴
// Lambda 形式
Function<String, Integer> len = s -> s.length();
// 方法引用形式
Function<String, Integer> len = String::length;
// 使用
len.apply("world"); // 5#五、构造器引用 🔴
// Lambda 形式
Supplier<ArrayList<String>> factory = () -> new ArrayList<>();
// 方法引用形式
Supplier<ArrayList<String>> factory = ArrayList::new;
// 带参数的构造器
Function<Integer, ArrayList<String>> factory2 = ArrayList::new;
factory2.apply(10); // new ArrayList<>(10)
// 用于 Stream
Stream<String> stream = Stream.of("a", "b", "c");
Stream<ArrayList<String>> mapped = stream.map(ArrayList::new);#六、方法引用与 Lambda 的选择 🟡
// 方法引用更简洁,可读性更好
// ✅ 优先使用方法引用
list.stream()
.map(String::toUpperCase) // 方法引用
.filter(String::isEmpty) // 方法引用
.forEach(System.out::println); // 方法引用
// ✅ Lambda 用于需要计算逻辑时
list.stream()
.map(s -> s.trim().toUpperCase()) // 需要组合操作
.filter(s -> s.length() > 3) // 简单计算#七、常见使用场景 🟡
// 1. Comparator
Comparator<String> c1 = (a, b) -> a.compareToIgnoreCase(b);
Comparator<String> c2 = String::compareToIgnoreCase;
// 2. Function
Function<String, String> trimUpper = String::trim.andThen(String::toUpperCase);
// 3. Consumer
Consumer<String> printer = System.out::println;
// 4. Predicate
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();#八、追问升级
面试官:"方法引用在编译后会变成什么?"
// 方法引用编译后使用 invokedynamic 指令
// 和 Lambda 类似,运行时通过 LambdaMetafactory 生成
// 静态方法引用:
// String::length 编译后
// invokedynamic # BootstrapMethod
// 相当于生成一个 CallSite 指向 String.length
// 实例方法引用(特定对象):
// str::length 相当于 lambda () -> str.length()
// 捕获了 str 对象