Java Optional所有方法使用

Java Optional所有方法使用

一. 创建 Optional 对象

  • Optional.of(T value)
    • 作用:用非 null 值创建 Optional。
    • 注意:参数为 null 会抛出 NullPointerException。
  • Optional.ofNullable(T value)
    • 作用:用值创建 Optional,允许值为 null。
  • Optional.empty()
    • 作用:创建一个空的 Optional。

示例:

Optional<String> opt = Optional.empty(); 

示例:

Optional<String> opt = Optional.ofNullable(null); // 返回 Optional.empty() 

示例:

Optional<String> opt = Optional.of("hello"); 

二. 判断和获取值

  • isPresent()
    • 作用:判断 Optional 是否有值(不是 empty)。
  • isEmpty()(Java 11+)
    • 作用:判断 Optional 是否为空。
  • get()
    • 作用:获取值。若为空则抛 NoSuchElementException。

示例:

String value = opt.get(); 

示例:

if(opt.isEmpty()) { System.out.println("没有值"); } 

示例:

if(opt.isPresent()) { System.out.println(opt.get()); } 

三. 值存在时的操作

  • ifPresent(Consumer<? super T> action)
    • 作用:如果有值,执行 action。
  • ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)(Java 9+)
    • 作用:有值执行 action,无值执行 emptyAction。

示例:

opt.ifPresentOrElse( val -> System.out.println(val), () -> System.out.println("没有值") ); 

示例:

opt.ifPresent(val -> System.out.println(val)); 

四. 提供默认值

  • orElse(T other)
    • 作用:有值返回该值,无值返回默认值。
  • orElseGet(Supplier<? extends T> supplier)
    • 作用:有值返回该值,无值调用 supplier 获取默认值(惰性)。
  • orElseThrow()(Java 10+)
    • 作用:有值返回该值,无值抛出 NoSuchElementException。
  • orElseThrow(Supplier<? extends X> exceptionSupplier)
    • 作用:有值返回该值,无值抛出指定异常。

示例:

String result = opt.orElseThrow(() -> new RuntimeException("没有值!")); 

示例:

String result = opt.orElseThrow(); 

示例:

String result = opt.orElseGet(() -> "默认值"); 

示例:

String result = opt.orElse("默认值"); 

五. 值转换

  • map(Function<? super T, ? extends U> mapper)
    • 作用:有值时对值进行转换并返回新的 Optional。
  • flatMap(Function<? super T, Optional> mapper)
    • 作用:有值时对值进行转换并返回 Optional,避免嵌套 Optional。
    • 示例:Optional<Integer> lenOpt = opt.flatMap(s -> Optional.of(s.length()));
  • filter(Predicate<? super T> predicate)
    • 作用:有值且满足条件则返回原 Optional,否则返回 empty。
    • 示例:Optional<String> filtered = opt.filter(s -> s.length() > 3);

示例:

Optional<Integer> lenOpt = opt.map(String::length); 

六. 其他方法(Java 9+)

  • stream()
    • 作用:将 Optional 转为 Stream(有值时为单元素流,否则为空流)。
    • 示例: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转换为流

八、进阶技巧

1. 与集合、流结合使用

在实际开发中,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())); 

2. 嵌套 Optional 的处理

如果你的对象结构很深,传统的 null 检查会很繁琐。使用 map 可以链式安全访问:

Optional<User> userOpt = Optional.ofNullable(user); String city = userOpt .map(User::getAddress) .map(Address::getCity) .orElse("未知城市"); 

这样可以避免多层 null 检查。

3. Optional 与异常处理结合

使用 orElseThrow 可以在缺失值时抛出自定义异常:

User user = optUser.orElseThrow(() -> new UserNotFoundException("用户不存在")); 

九、常见误区

  1. 不要将 Optional 用作字段类型
    • Optional 设计初衷是作为返回值类型,不建议用作类的属性字段(成员变量),会增加序列化和内存复杂度。
  2. 不要滥用 get() 方法
    • get() 只在你确定有值时使用,否则建议用 orElseorElseThrow 等方法。
  3. 不要在集合中使用 Optional
    • List<Optional> 不是最佳实践,应该用 Optional<List> 或直接用空集合表示无数据。

推荐做法:

public Optional<User> findUserById(Long id) { ... } 

不推荐:

class User { private Optional<String> name; // 不推荐 } 

十、最佳实践

  • 方法返回值建议用 Optional 表示可能缺失的值。
  • 使用 mapflatMapfilter 进行链式操作,避免嵌套 if-null 判断。
  • 用 orElseGet 替代 orElse,当默认值计算较为复杂或耗时时(惰性计算)。
  • 用 ifPresentOrElse(Java 9+)简化有值/无值的分支逻辑。

十一、实际应用场景举例

1. 数据库查询

public Optional<User> findById(Long id) { User user = jdbcTemplate.queryForObject(...); return Optional.ofNullable(user); } 

2. 配置参数读取

Optional<String> config = Optional.ofNullable(System.getProperty("my.config")); String value = config.orElse("默认配置"); 

3. RESTful 接口返回值

@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); 

十四、与其他框架结合

1. 与 Spring 框架结合

Spring Data JPA 的查询接口可以直接返回 Optional:

public interface UserRepository extends JpaRepository<User, Long> { Optional<User> findByUsername(String username); } 

这样调用者必须处理可能为空的情况,API更安全。

2. 与 Stream 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; ... } 
  • 如果 value 为 null,则表示 empty。
  • 所有方法都围绕这个 value 做判断和操作。
  • Optional 的实例是不可变的(immutable)。

例如,map 方法源码片段:

public <U> Optional<U> map(Function<? super T, ? extends U> mapper) { if (!isPresent()) return empty(); else return Optional.ofNullable(mapper.apply(value)); } 

这保证了链式调用的安全性。


十六、复杂业务场景举例

1. 多层嵌套属性安全访问

传统写法容易出现 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); 

代码更简洁、更安全。

2. API响应处理

比如你有一个外部接口返回 Optional,结合响应式编程:

public Optional<User> getUserFromApi(String id) { // 调用外部接口 } public void processUser(String id) { getUserFromApi(id) .ifPresentOrElse( user -> save(user), () -> log.warn("用户未找到") ); } 

十七、常见面试题

  1. Optional 的作用是什么?
    • 避免空指针异常,提升代码可读性和安全性。
  2. Optional 的 map 和 flatMap 有什么区别?
    • map 用于值转换,flatMap 用于避免嵌套 Optional。
  3. Optional 可以作为成员变量吗?
    • 不推荐。只建议用作方法返回值类型。
  4. 如何优雅地处理多层嵌套对象的 null?
    • 用 Optional 的链式 map。

十八、其他扩展用法

1. 自定义 Optional 工具方法

你可以封装一些通用操作:

public static <T> T getOrDefault(Optional<T> opt, T defaultValue) { return opt.orElse(defaultValue); } 

2. Optional 与枚举结合

Optional<Status> statusOpt = Optional.ofNullable(Status.fromCode(code)); statusOpt.ifPresent(status -> handle(status)); 

十九、常见坑与注意事项

  • 不要在序列化对象时用 Optional(Jackson等可能不支持)。
  • Optional 不是万能的,业务逻辑复杂时仍需合理判空。
  • Optional 不能替代所有的 null 检查,但能显著减少出错概率。

二十、总结

Optional 的核心价值:

  • 明确表达“值可能缺失”的语义。
  • 支持函数式、链式操作,简化代码。
  • 强制调用者处理缺失值,减少 NPE。

用法精髓:

  • 只在返回值用 Optional,不在字段、参数用 Optional。
  • 善用 map、flatMap、filter、orElse、orElseGet、orElseThrow。
  • 与 Stream、Lambda、Spring 等现代 Java 技术结合,写出更优雅的代码。

Read more

Gemma 3模型:Google 开源新星,大语言模型未来探索

Gemma 3模型:Google 开源新星,大语言模型未来探索

🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、快速发展的AI世界:为何关注Gemma 3? 2、Gemma 模型的背景:Google 的开源承诺 二、Gemma 3 基础:什么是 Gemma? 1、Gemma 模型的诞生和设计理念 2、Gemma 模型的优势与特点 三、Gemma 3 技术深度解析 1、Gemma 3 的架构 2、模型训练与优化 3、不同尺寸 Gemma 模型对比 一、引言 1、快速发展的AI世界:为何关注Gemma

By Ne0inhk
开源 MaxKB 深度解读

开源 MaxKB 深度解读

引言:AI 落地的现实困境与 MaxKB 的解决方案   在人工智能渗透各行各业的今天,多数企业仍面临技术门槛高、部署成本高、迭代周期长的现实问题。MaxKB(全称 "Max Knowledge Brain")作为一款企业级智能体平台,以开源易用、可逐步拓展的特性,为这些问题提供了可行的解决路径。该平台在 GitHub 累计获得 19K+ Stars,安装量超 50 万次,日均下载量逾 1000 次,已覆盖 30 余个行业的 1000 余家企业。本文结合官方技术方案、实操截图与应用案例,从技术内核、实操落地、行业价值三大维度,对其进行全面拆解。 一、技术内核拆解:从 RAG 到 Agent 的全栈架构 1.

By Ne0inhk

git: worktree命令介绍和使用

文章目录 * 一、基本概念 * 二、常用命令 * 三、使用示例 * 1. 创建一个新的 worktree * 2. 查看所有 worktree * 3. 删除 worktree * 四、注意事项 * 五、典型使用场景 * 六、兼容性 git worktree 是 Git 提供的一个强大功能,允许你在同一个 Git 仓库中同时检出多个分支,而无需克隆多个副本。每个工作树(worktree)都有独立的工作目录、暂存区和 HEAD,但共享同一个 .git 仓库对象数据库,从而节省磁盘空间和提升效率。 https://git-scm.com/docs/git-worktree/zh_HANS-CN 一、基本概念 * 主工作树(

By Ne0inhk
腾讯版“免部署小龙虾“WorkBuddy,平替开源OpenClaw,无需抢购Mac Mini,所有电脑均可部署安装!0元养虾!

腾讯版“免部署小龙虾“WorkBuddy,平替开源OpenClaw,无需抢购Mac Mini,所有电脑均可部署安装!0元养虾!

前言:AI Agent时代来了,你还在为"养虾"发愁? 最近,开源AI智能体OpenClaw(被网友亲切称为"小龙虾")火遍全网,GitHub星标数超过24.8万,登顶星标榜第一!它能自动盯盘、写周报、修代码,甚至操作你的电脑完成复杂任务,堪称"数字员工"。 然而,想养这只"虾"可不容易: 需要抢购Mac Mini(M1/M2芯片,内存16GB起步) 要手动配置Docker、API密钥、网络环境 命令行操作复杂,普通用户往往耗费数小时仍无法成功运行 好消息来了!腾讯云正式推出WorkBuddy—— 腾讯版"免部署小龙虾",完全兼容OpenClaw技能,但无需配置、

By Ne0inhk