一、Optional 类
Optional 是 Java 8 引入的一个容器类,用来表示 一个值可能存在,也可能不存在。
它的核心目的是:
避免显式的 null 判断,从而减少
NullPointerException。
传统代码:
User user = getUser();
if (user != null) {
System.out.println(user.getName());
}
使用 Optional:
Optional<User> userOpt = getUser();
userOpt.ifPresent(user -> System.out.println(user.getName()));
Optional 本质上是一个 值容器(Value Container):
Optional
├── 有值 (value)
└── 空值 (empty)
二、创建 Optional 对象
Optional 提供了三种常见的创建方式。
1 Optional.empty()
创建一个 空 Optional。
Optional<String> emptyOpt = Optional.empty();
适用于:
- 方法返回空值
- 表示明确的不存在
2 Optional.of()
创建一个 必须非空的 Optional。
如果传入 null,会抛出 NullPointerException。
Optional<String> opt = Optional.of("Hello");
错误示例:
Optional.of(null); // 抛出 NullPointerException
适用场景:
- 明确知道值 一定不为 null
3 Optional.ofNullable()
创建一个 允许为 null 的 Optional。
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);
如果值为 null:
Optional.empty()
企业开发中:
99% 使用 ofNullable
三、判断 Optional 是否存在值
1 isPresent()
判断是否存在值。
Optional<String> opt = Optional.of("Hello");
if (opt.isPresent()) {
System.out.println(opt.get());
}
但这种写法 并不推荐。
原因:
isPresent + get = 传统 null 判断写法
2 ifPresent()
如果值存在,则执行操作。
Optional<String> opt = Optional.of("Hello");
opt.ifPresent(value -> {
System.out.println(value);
});
推荐写法:
opt.ifPresent(System.out::println);
四、获取 Optional 的值
1 get()
直接获取值。
String value = opt.get();
如果为空:
NoSuchElementException
开发中不推荐使用 get()
原因:
get() == 可能抛异常
2 orElse()
如果为空返回默认值。
String value = opt.orElse("Default");
示例:
Optional<String> opt = Optional.empty();
String value = opt.orElse("Default Value");
输出:
Default Value
3 orElseGet()
通过 Supplier 获取默认值。
String value = opt.orElseGet(() -> "Default Value");
区别:
| 方法 | 特点 |
|---|---|
| orElse | 默认值会提前计算 |
| orElseGet | 只有为空时才执行 |
示例:
opt.orElse(expensiveMethod());
opt.orElseGet(() -> expensiveMethod());
推荐:
优先使用 orElseGet
4 orElseThrow()
如果为空,抛出指定异常。
String value = opt.orElseThrow(() ->
new IllegalArgumentException("Value not present"));
常见写法:
User user = userOpt.orElseThrow(() ->
new RuntimeException("用户不存在"));
五、Optional 的转换操作
Optional 的一个重要能力是 函数式转换。
1 map()
如果存在值,执行转换。
Optional<String> opt = Optional.of("Hello");
Optional<Integer> lengthOpt = opt.map(String::length);
结果:
Optional[5]
获取:
System.out.println(lengthOpt.orElse(0));
2 flatMap()
用于 避免 Optional 嵌套。
错误写法:
Optional<Optional<Integer>>
正确写法:
Optional<String> opt = Optional.of("Hello");
Optional<Integer> lengthOpt =
opt.flatMap(v -> Optional.of(v.length()));
区别:
| 方法 | 返回 |
|---|---|
| map | Optional |
| flatMap | Optional<Optional> |
六、Optional 过滤
filter()
如果满足条件,保留值,否则返回空。
Optional<String> opt = Optional.of("Hello");
Optional<String> result =
opt.filter(value -> value.startsWith("H"));
示例:
result.ifPresent(System.out::println);
输出:
Hello
不满足条件:
Optional.empty()
七、Java 9 新增方法
1 ifPresentOrElse()
值存在执行一个逻辑,否则执行另一个。
opt.ifPresentOrElse(
value -> System.out.println("Value: " + value),
() -> System.out.println("Value not present")
);
2 stream()
将 Optional 转换为 Stream。
Optional<String> opt = Optional.of("Hello");
opt.stream().forEach(System.out::println);
适用于:
Stream + Optional 组合
示例:
List<Optional<String>> list = List.of(
Optional.of("A"),
Optional.empty(),
Optional.of("B")
);
list.stream()
.flatMap(Optional::stream)
.forEach(System.out::println);
输出:
A
B
八、开发最佳实践
1 不要用 Optional 作为字段
错误:
class User {
Optional<String> name;
}
正确:
class User {
String name;
}
原因:
- 序列化问题
- ORM 不支持
- 增加复杂度
2 不要作为方法参数
错误:
void save(Optional<String> name)
正确:
void save(String name)
3 Optional 只用于返回值
推荐:
Optional<User> findUser(Long id)
4 不要滥用 Optional
错误:
Optional.of(user)
正确:
Optional.ofNullable(user)
九、使用示例
例如:
查询用户。
传统写法:
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("用户不存在");
}
return user.getName();
Optional 写法:
return userRepository.findById(id)
.map(User::getName)
.orElseThrow(() -> new RuntimeException("用户不存在"));
优势:
- 无 null 判断
- 代码更简洁
- 函数式风格
十、Optional 常用方法总结
| 方法 | 作用 |
|---|---|
| of | 创建非空 Optional |
| ofNullable | 创建可能为空 Optional |
| empty | 创建空 Optional |
| isPresent | 是否存在值 |
| ifPresent | 存在时执行 |
| get | 获取值(不推荐) |
| orElse | 默认值 |
| orElseGet | Supplier 默认值 |
| orElseThrow | 为空抛异常 |
| map | 转换 |
| flatMap | 避免嵌套 |
| filter | 过滤 |