Objects 与 Optional
约 888 字大约 3 分钟
布欧-Lewyon
2026-05-16
首页 › Java › 核心类库 › Objects 与 Optional
java.util.Objects 和 java.util.Optional 是 Java 7/8 引入的实用工具类,专注于null 安全。前者提供空值判别的静态方法,后者用容器封装可能缺失的值,迫使调用者显式处理"空"的情况。
Objects 工具类
Objects 提供了一组静态方法,减少 if (x != null) 样板代码:
Objects.equals("a", "a"); // true(内部做了 null 安全比较)
Objects.equals(null, "a"); // false(不会 NPE)
Objects.equals(null, null); // true
// isNull / nonNull —— 常用在 Stream 过滤中
Stream.of("a", null, "b")
.filter(Objects::nonNull)
.collect(Collectors.toList());
// requireNonNull —— 方法参数校验
public UserService(UserRepository repo) {
this.repo = Objects.requireNonNull(repo, "repo 不能为 null");
}
// toString —— 安全转字符串
Objects.toString(obj, "默认值");
// hashCode —— 安全计算哈希
Objects.hash(field1, field2); // 组合计算多个字段的哈希
// compare —— null 安全的比较
Objects.compare(a, b, Comparator.naturalOrder());null 安全比较指南
// 不推荐(繁琐且容易忘判空)
if (str != null && str.equals("value"))
// 推荐(Objects.equals 内部判空)
if (Objects.equals(str, "value"))Optional:容器化的 null
Optional<T> 是一个容器,可能包含非 null 值或为空,用于方法返回值,告知调用者"值可能不存在"。
创建 Optional
Optional<String> opt1 = Optional.of("hello"); // 值不能为 null
Optional<String> opt2 = Optional.ofNullable(someVar); // 可为 null
Optional<String> opt3 = Optional.empty(); // 空容器安全取值
// 推荐:提供默认值
String name = opt.orElse("未知");
String name2 = opt.orElseGet(() -> fetchDefault()); // 惰性求值
String name3 = opt.orElseThrow(() -> new NotFoundException("未找到"));
// 不推荐:直接 get(值缺失时抛 NoSuchElementException)
String raw = opt.get();orElse 与 orElseGet 的区别:
orElse(default)始终计算default表达式,即使 Optional 有值。orElseGet(supplier)仅当 Optional 为空时才调用 Supplier。- 如果默认值的计算开销大或有副作用,用
orElseGet。
常用操作
// 消费
opt.ifPresent(val -> System.out.println(val));
// 转换
opt.map(String::toUpperCase)
.filter(v -> v.length() > 3)
.orElse("FALLBACK");
// 展平(避免 Optional<Optional<String>>)
opt.flatMap(v -> Optional.of(v.trim()));
// 链式调用
User user = userRepo.findById(id)
.orElseThrow(() -> new NotFoundException("用户不存在"));使用边界
适合:方法返回值可能为空,用 Optional 让调用者明确处理。 不适合:
// ❌ 字段类型
public class User {
private Optional<String> email; // 序列化问题,不推荐
}
// ❌ 方法参数
public void process(Optional<String> input) { } // 增加调用方复杂度
// ❌ 集合中的元素
List<Optional<String>> list; // 集合本身 isEmpty 就够了Optional 不是通用 null 替代品,它的设计目的就是返回值。
实战:安全链式调用
// 场景:获取用户的订单地址所在城市
// 传统方式(多层判空)
String city = null;
if (user != null) {
Order order = user.getLatestOrder();
if (order != null) {
Address addr = order.getAddress();
if (addr != null) {
city = addr.getCity();
}
}
}
// Optional 方式(声明式)
String city2 = Optional.ofNullable(user)
.map(User::getLatestOrder)
.map(Order::getAddress)
.map(Address::getCity)
.orElse("未知城市");小结
Objects提供equals、hash、requireNonNull、toString、isNull/nonNull等 null 安全工具方法。Optional用于方法返回值,迫使调用者处理"值不存在"的情况,避免 NPE。map做值转换,flatMap展平嵌套 Optional,orElse/orElseGet/orElseThrow做兜底。- Optional 不应用于字段、方法参数或集合元素。
- 易错:
Optional.of(null)抛 NPE,应用Optional.ofNullable。orElse(default)无论值是否存在都会计算 default,若计算有开销应改用orElseGet。此外,Optional本身可序列化但不推荐——反序列化后容器语义可能被误解。 - 思考任务:有一个
List<Person>,每人可能有Spouse,每人有Address。用 Optional 链式调用获取所有人的配偶地址中的城市名,空值用 "未知" 填充。
上一节:注解
下一节:大数计算与精度
