【后端】Java 8 特性 `User::getId` 语法(方法引用)介绍
文章目录
- 核心概念解析:
- 方法引用的四种类型:
- 关键特性:
- 使用场景推荐:
- 何时避免使用:
- 性能说明:
在 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 和方法引用之间自动转换。