一、创建 Optional 对象
- Optional.of(T value)
系统介绍了 Java Optional 类的核心 API,涵盖对象创建、值判断与获取、条件操作、默认值处理及映射转换等方法。内容包含实战代码示例、Spring 集成方案、源码原理分析及常见误区(如字段类型滥用),旨在帮助开发者利用函数式编程特性避免空指针异常,提升代码健壮性与可读性。

示例:
Optional<String> opt = Optional.empty();
示例:
Optional<String> opt = Optional.ofNullable(null); // 返回 Optional.empty()
示例:
Optional<String> opt = Optional.of("hello");
示例:
String value = opt.get();
示例:
if(opt.isEmpty()) { System.out.println("没有值"); }
示例:
if(opt.isPresent()) { System.out.println(opt.get()); }
示例:
opt.ifPresentOrElse( val -> System.out.println(val), () -> System.out.println("没有值") );
示例:
opt.ifPresent(val -> System.out.println(val));
示例:
String result = opt.orElseThrow(() -> new RuntimeException("没有值!"));
示例:
String result = opt.orElseThrow();
示例:
String result = opt.orElseGet(() -> "默认值");
示例:
String result = opt.orElse("默认值");
Optional<Integer> lenOpt = opt.flatMap(s -> Optional.of(s.length()));Optional<String> filtered = opt.filter(s -> s.length() > 3);示例:
Optional<Integer> lenOpt = opt.map(String::length);
opt.stream().forEach(System.out::println);Optional<String> opt = Optional.ofNullable("abc");
// 判断是否有值
if (opt.isPresent()) { System.out.println(opt.get()); }
// 转换值
int len = opt.map(String::length).orElse(0);
// 过滤
opt.filter(s -> s.startsWith("a")).ifPresent(System.out::println);
// 默认值
String val = opt.orElse("default");
// 异常处理
String mustHave = opt.orElseThrow(() -> new IllegalArgumentException("必须有值"));
| 方法名 | 主要用途 |
|---|---|
| of, ofNullable, empty | 创建 Optional |
| isPresent, isEmpty | 判断是否有值 |
| get | 获取值(不推荐直接用) |
| ifPresent, ifPresentOrElse | 有值时执行操作 |
| orElse, orElseGet, orElseThrow | 提供默认值或异常处理 |
| map, flatMap | 值转换 |
| filter | 条件过滤 |
| stream | 转换为流 |
在实际开发中,Optional 常与 Stream API 配合,用于处理可能为空的集合元素:
List<User> users = ...;
Optional<User> optUser = users.stream()
.filter(u -> u.getName().equals("张三"))
.findFirst();
optUser.ifPresent(u -> System.out.println(u.getEmail()));
如果你的对象结构很深,传统的 null 检查会很繁琐。使用 map 可以链式安全访问:
Optional<User> userOpt = Optional.ofNullable(user);
String city = userOpt
.map(User::getAddress)
.map(Address::getCity)
.orElse("未知城市");
这样可以避免多层 null 检查。
使用 orElseThrow 可以在缺失值时抛出自定义异常:
User user = optUser.orElseThrow(() -> new UserNotFoundException("用户不存在"));
get() 只在你确定有值时使用,否则建议用 orElse、orElseThrow 等方法。推荐做法:
public Optional<User> findUserById(Long id) { ... }
不推荐:
class User {
private Optional<String> name; // 不推荐
}
map、flatMap、filter 进行链式操作,避免嵌套 if-null 判断。orElseGet 替代 orElse,当默认值计算较为复杂或耗时时(惰性计算)。ifPresentOrElse(Java 9+)简化有值/无值的分支逻辑。public Optional<User> findById(Long id) {
User user = jdbcTemplate.queryForObject(...);
return Optional.ofNullable(user);
}
Optional<String> config = Optional.ofNullable(System.getProperty("my.config"));
String value = config.orElse("默认配置");
@GetMapping("/user/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
假设你有一个订单系统,需要安全地获取订单的收货人城市:
public Optional<Order> findOrder(Long orderId) { // 查询订单 }
public String getReceiverCity(Long orderId) {
return findOrder(orderId)
.map(Order::getReceiver)
.map(Receiver::getAddress)
.map(Address::getCity)
.filter(city -> !city.isEmpty())
.orElse("未知城市");
}
这样可以保证即使任何一环为 null,也不会抛出异常,并且逻辑清晰。
// 创建
Optional<String> opt = Optional.ofNullable(value);
// 判断
opt.isPresent();
opt.isEmpty(); // Java 11+
// 获取
opt.get(); // 不推荐
opt.orElse("默认值");
opt.orElseGet(() -> "默认值");
opt.orElseThrow(() -> new RuntimeException("没有值"));
// 转换
opt.map(String::length);
opt.flatMap(s -> Optional.of(s.length()));
// 过滤
opt.filter(s -> s.length() > 3);
// 条件执行
opt.ifPresent(System.out::println);
opt.ifPresentOrElse(
System.out::println,
() -> System.out.println("没有值")
);
// 与流结合
opt.stream().forEach(System.out::println);
Spring Data JPA 的查询接口可以直接返回 Optional:
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
这样调用者必须处理可能为空的情况,API 更安全。
你可以在流操作中用 Optional 优雅处理可能缺失的值:
List<String> names = Arrays.asList("Tom", null, "Jerry");
names.stream()
.map(Optional::ofNullable)
.flatMap(Optional::stream) // Java 9+
.forEach(System.out::println);
这可以过滤掉 null 值,避免 NPE。
Optional 的核心是一个 final 字段 value:
public final class Optional<T> {
private final T value;
...
}
例如,map 方法源码片段:
public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
if (!isPresent()) return empty();
else return Optional.ofNullable(mapper.apply(value));
}
这保证了链式调用的安全性。
传统写法容易出现 null 检查地狱:
if (order != null && order.getReceiver() != null && order.getReceiver().getAddress() != null) {
String city = order.getReceiver().getAddress().getCity();
}
Optional 链式写法:
Optional.ofNullable(order)
.map(Order::getReceiver)
.map(Receiver::getAddress)
.map(Address::getCity)
.ifPresent(System.out::println);
代码更简洁、更安全。
比如你有一个外部接口返回 Optional,结合响应式编程:
public Optional<User> getUserFromApi(String id) { // 调用外部接口 }
public void processUser(String id) {
getUserFromApi(id)
.ifPresentOrElse(
user -> save(user),
() -> log.warn("用户未找到")
);
}
你可以封装一些通用操作:
public static <T> T getOrDefault(Optional<T> opt, T defaultValue) {
return opt.orElse(defaultValue);
}
Optional<Status> statusOpt = Optional.ofNullable(Status.fromCode(code));
statusOpt.ifPresent(status -> handle(status));
Optional 的核心价值:
用法精髓:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online