Optional的新用法,巧用Java 8 新特性,让代码更优雅

 今天分享的事java8的新特性中的Optional,让我们看看平常武器的东西用出新花样。可能大家对 Optional有点陌生,我们先熟悉下它的常规操作再开始文末展示新花样怎么用。一、背景在 Java 8 中引入的 java.util.Optional 是一个容器类,用于封装一个 “可能为 null” 的值。它的核心作用是明确表示 “值可能存在或不存在”,从而替代直接使用 null,减少空指针异常(NPE),并让代码意图更清晰。

二、为什么需要 Optional?

在传统 Java 开发中,若方法可能返回 null,调用方往往需要手动判断 null(如 if (obj != null)),否则可能触发 NPE。而 Optional 通过 “包装” 可能为 null 的值,强制调用方处理 “值不存在” 的场景,从而避免遗漏 null 检查。

例如,对于可能返回 null 的 student.getEduScore(),传统写法需要显式判断:

BigDecimal score = student.getEduScore();if (score != null) {    // 处理非 null 情况} else {    // 处理 null 情况}

使用 Optional 后,代码会更明确地体现 “值可能不存在” 的意图:

Optional<BigDecimal> scoreOpt = Optional.ofNullable(student.getEduScore());// 必须显式处理“存在”和“不存在”两种情况

三、Optional 基本用法

1. 创建 Optional 实例

Optional 提供了 3 种创建实例的方法,分别对应不同场景:

方法说明适用场景
Optional.of(T value)包装一个非 null 值,若 value 为 null 则直接抛 NPE。确定值一定非 null 时
Optional.ofNullable(T value)包装一个可能为 null 的值,若 value 为 null 则返回空 Optional。不确定值是否为 null 时
Optional.empty()返回一个空的 Optional(内部值为 null)。明确表示 “值不存在” 时

示例

// 1. of():值一定非 null(如新建的对象)String name = "张三";Optional<String> nameOpt = Optional.of(name); // 正确// 若值为 null,of() 会抛 NPE(错误用法)String nullName = null;Optional<String> errorOpt = Optional.of(nullName); // 抛出 NullPointerException// 2. ofNullable():值可能为 null(如从数据库查询的结果)BigDecimal score = student.getEduScore(); // 可能返回 nullOptional<BigDecimal> scoreOpt = Optional.ofNullable(score); // 安全// 3. empty():明确表示“无值”Optional<String> emptyOpt = Optional.empty(); // 空容器

2. 判断值是否存在

通过 isPresent() 方法判断 Optional 中是否包含非 null 值:

Optional<BigDecimal> scoreOpt = Optional.ofNullable(student.getEduScore());if (scoreOpt.isPresent()) {    System.out.println("成绩存在:" + scoreOpt.get());} else {    System.out.println("成绩不存在");}

Java 11 新增了 isEmpty() 方法(与 isPresent() 相反),更符合直觉:

if (scoreOpt.isEmpty()) {    System.out.println("成绩不存在");}

3. 获取值(避免直接用 get()

Optional 提供了多种获取值的方法,其中 get() 是最危险的,需特别注意:

  • get():直接返回内部值,若值不存在(空 Optional)则抛 NoSuchElementException
    仅建议在确定值一定存在时使用(如先通过 isPresent() 验证)。
  • orElse(T other):若值存在则返回该值,否则返回指定的默认值 other
    (无论值是否存在,other 都会被提前创建,适合简单默认值)
  • orElseGet(Supplier<? extends T> supplier):若值存在则返回该值,否则通过 supplier 函数生成默认值。
    supplier 仅在值不存在时执行,适合复杂默认值,避免不必要的计算)
  • orElseThrow(Supplier<? extends X> exceptionSupplier):若值存在则返回该值,否则抛出 exceptionSupplier 生成的异常。
    (适合 “值不存在时必须报错” 的场景,如业务上必填的字段)
Optional<BigDecimal> scoreOpt = Optional.ofNullable(student.getEduScore());// 1. get():仅在确定值存在时使用if (scoreOpt.isPresent()) {    BigDecimal score = scoreOpt.get(); // 安全}// 2. orElse():空值时返回默认值 0BigDecimal score1 = scoreOpt.orElse(BigDecimal.ZERO);// 3. orElseGet():空值时通过函数生成默认值(更高效)BigDecimal score2 = scoreOpt.orElseGet(() -> calculateDefaultScore());// 4. orElseThrow():空值时抛自定义异常BigDecimal score3 = scoreOpt.orElseThrow(() ->     new IllegalArgumentException("学生成绩不能为空"));

四、新花样使用方法用Optional代替if()else。一行代码解决了传统4行代码,技术没有最好的,只有最合适的

BigDecimal currentScore = Optional.ofNullable(student.getEduScore()).orElse(BigDecimal.Z

声明:来自全栈的程序员,仅代表创作者观点。链接:https://eyangzhen.com/2902.html

全栈的程序员的头像全栈的程序员

相关推荐

关注我们
关注我们
购买服务
购买服务
返回顶部