文章目錄
- 核心概念解析:
- 方法引用的四種類型:
- 關鍵特性:
- 使用場景推薦:
- 何時避免使用:
- 性能說明:
在 Java 中,
User::getId
是一種稱為
方法引用(Method Reference) 的語法糖,它本質上是一個簡化版的 Lambda 表達式,專門用于引用現有的方法。
核心概念解析:
-
方法引用是什么?
- 一種更簡潔的 Lambda 表達式寫法
- 語法:
ClassName::methodName
- 底層等同于:
(參數) -> ClassName.methodName(參數)
-
User::getId
具體含義:// 兩者完全等價: Collectors.groupingBy(User::getId)// 原始 Lambda 形式 Collectors.groupingBy(user -> user.getId())
-
執行機制:
- Stream 遍歷每個
User
對象 - 調用該對象的
getId()
方法 - 將返回值用作分組依據
// 偽代碼實現邏輯 Map<Long, List<User>> map = new HashMap<>(); for (User user : userList) {Long id = user.getId(); // 這就是 User::getId 實際執行的操作map.computeIfAbsent(id, k -> new ArrayList<>()).add(user); }
- Stream 遍歷每個
方法引用的四種類型:
類型 | 語法 | 等價 Lambda | 示例 |
---|---|---|---|
1. 靜態方法引用 | Class::staticMethod | (args) -> Class.staticMethod(args) | Math::sqrt |
2. 實例方法引用 | Class::instanceMethod | (obj, args) -> obj.instanceMethod(args) | User::getId |
3. 特定對象方法引用 | object::instanceMethod | (args) -> object.instanceMethod(args) | System.out::println |
4. 構造器引用 | Class::new | (args) -> new Class(args) | ArrayList::new |
User::getId
屬于第二種類型:實例方法引用(無參數)
關鍵特性:
-
類型推斷:編譯器自動推斷參數類型為
User
-
空指針風險:若
user
為null
會拋出 NPE -
方法匹配要求:要求方法簽名匹配函數式接口
// groupingBy 需要 Function 接口 public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
此處
User::getId
匹配為:Function<User, Long> classifier = User::getId;
使用場景推薦:
- 集合操作:
list.stream().map(User::getName)
- 排序:
Collections.sort(users, Comparator.comparing(User::getBirthDate))
- 替代簡單 Lambda:當僅調用單個方法時優先使用方法引用
何時避免使用:
// 需要額外操作時不適用:
users.stream().map(user -> {log.debug("Processing user: {}", user); return user.getId();}) // 需要多行操作,不能簡化為方法引用// 需要空值檢查:
users.stream().map(user -> user != null ? user.getId() : null) // 無法用方法引用表達
性能說明:
- 編譯后與 Lambda 表達式生成相同字節碼
- 無運行時性能差異
- 本質是編譯器提供的語法糖
💡 專業提示:在 IntelliJ IDEA 中,可使用 Alt+Enter 在 Lambda 和方法引用之間自動轉換。