Java 的 Optional
是 Java 8 引入的一个容器类,旨在更优雅地处理可能为 null
的值,避免显式的 null
检查和空指针异常(NullPointerException
)。它的核心思想是强制开发者明确处理“值可能不存在”的情况,而不是隐式忽略。
一、Optional 的核心作用
显式表示“值可能缺失”:通过类型系统提示调用者需要处理空值。
减少 null
检查代码:提供链式方法替代嵌套的 if (obj != null)
。
避免空指针异常:通过安全的方法访问潜在的空值。
二、创建 Optional 对象
// 1. 创建一个非空值的 Optional(若值为 null 会抛出 NPE)
Optional<String> optional1 = Optional.of("Hello");
// 2. 创建一个可能为 null 的 Optional
String value = getNullableValue(); // 可能返回 null
Optional<String> optional2 = Optional.ofNullable(value);
// 3. 创建一个空的 Optional
Optional<String> optional3 = Optional.empty();
三、Optional 的常用方法
1. 检查值是否存在
-
isPresent()
:判断值是否存在。 -
isEmpty()
(Java 11+):判断值是否为空。
if (optional.isPresent()) {
System.out.println("值存在: " + optional.get());
}
2. 值存在时执行操作
-
ifPresent(Consumer)
: 值存在时执行操作。
optional.ifPresent(v -> System.out.println("值为: " + v));
3. 获取值
-
get()
:直接获取值(若值为空会抛异常,需谨慎使用)。 -
orElse(T)
: 值存在时返回值,否则返回默认值。 -
orElseGet(Supplier)
: 延迟生成默认值。 -
orElseThrow()
: 值不存在时抛出异常(可自定义异常)。
String result = optional.orElse("默认值");
String result = optional.orElseGet(() -> generateDefault());
String result = optional.orElseThrow(() -> new NotFoundException("值不存在"));
4. 链式操作
-
map(Function)
: 对值进行转换(若值为空,直接返回空 Optional)。 -
flatMap(Function)
: 与map
类似,但用于返回 Optional 的函数。 -
filter(Predicate)
: 过滤值,不满足条件则返回空 Optional。
Optional<String> upperCase = optional.map(String::toUpperCase);
Optional<Integer> length = optional.flatMap(v -> Optional.of(v.length()));
Optional<String> filtered = optional.filter(v -> v.length() > 3);
四、使用场景
方法返回值:明确表示返回值可能为空。
public Optional<User> findUserById(int id) {
// 查询数据库,可能返回 null
return Optional.ofNullable(userRepository.findById(id));
}
链式处理可能为空的值:
String city = userOptional
.map(User::getAddress)
.map(Address::getCity)
.orElse("未知城市");
替代 if-else
嵌套:
// 传统方式
if (user != null && user.getAddress() != null) {
// ...
}
// Optional 方式
userOptional.flatMap(User::getAddress).ifPresent(address -> {
// ...
});
五、最佳实践与注意事项
避免以下情况:
将 Optional
作为字段、方法参数或集合元素(违背设计初衷)。
过度使用 Optional
,导致代码冗余。
直接调用 get()
而不检查是否存在值。
优先使用 orElse/orElseGet
替代 isPresent()
:
// 不推荐
if (optional.isPresent()) {
return optional.get();
} else {
return "default";
}
// 推荐
return optional.orElse("default");
与 Stream 结合使用:
List<String> names = users.stream()
.map(user -> user.getName().orElse("匿名"))
.collect(Collectors.toList());
六、完整示例
public class OptionalDemo {
public static void main(String[] args) {
Optional<String> optional = Optional.ofNullable(getNullableString());
String value = optional
.map(String::toUpperCase)
.filter(s -> s.length() > 3)
.orElse("DEFAULT");
System.out.println(value); // 输出 "DEFAULT" 或处理后的值
}
private static String getNullableString() {
return Math.random() > 0.5 ? "hello" : null;
}
}