Optional

本文探讨了Java8中Optional类的作用及其在代码中避免空指针异常的应用方式,并对比了Guava提供的替代方案。

Optional

作为一名Java开发者,在开发过程中,判断是否为空是让我纠结的几个点之一,听说Java 8提供了一个Optional类用于解决这个问题,我已经迫不及待要去了解他了。

  • 作用
    • 经过研究使用之后,得出一个结论:Optional类其实是用一种具象的方式来避免开发者忘记判空,具体来说就是,Optional是一种傻瓜式的方式,因为Null自身的可读性是很差的,所以利用Optional包裹操作对象,强行用可读文字来提醒开发者需要考虑操作对象为空的可能性,例如if(optional.isPresent())相对于if (xxx==null),可读性就强了很多,而且Optional还提供了or(Supplier<? extends T> supplier),可以利用lambda表达式简化代码,例如nameOptional.or(()->"name is absent"),当name为空时,就会执行括号中的lambda表达式,返回”name is absent”,之前的版本中还提供了isPresent()方法也支持lambda,但是后来移除了,不知道是基于什么考虑;
    • 另外,Guava还提供了一些方法用于避免手动判空:
      • Strings
        • emptyToNull(String)
        • isNullOrEmpty(String)
        • nullToEmpty(String)
      • Preconditions
        • checkNotNull(T reference)
  • 用法
    • Google在JDK之外提供了一个类似开发者工具类库的开发包Guava(番石榴:瓜娃),Optional就是Guava提供的,所以首先需要在Gradle中引入compile 'com.google.guava:guava:19.0'
    • 详细用法:官方介绍的很详细
  • 意义
    • 还没有在具体开发中使用Optinal,所以先挖坑,后面来填。
### Optional使用方法 `Optional` 是 Java 8 引入的一个容器类,用于处理可能为 `null` 的值,从而避免空指针异常(NullPointerException, NPE)。它提供了一系列方法来优雅地处理空值问题。 #### 创建 Optional 实例 - **`empty()`**:创建一个空的 `Optional` 实例,适用于值确实为空的情况。 - **`of(T value)`**:创建一个包含非空值的 `Optional` 实例。如果传入的值为 `null`,会抛出 `NullPointerException`。 - **`ofNullable(T value)`**:创建一个 `Optional` 实例,如果值为 `null`,则返回一个空的 `Optional`,而不是抛出异常 [^2]。 #### 获取值 - **`get()`**:返回 `Optional` 中包装的值。在调用前必须确保值存在,否则会抛出异常。 - **`isPresent()`**:判断 `Optional` 中是否有值,返回布尔值。 - **`ifPresent(Consumer<? super T> consumer)`**:如果值存在,则执行给定的消费者操作,否则不执行任何操作 [^1]。 #### 提供默认值或抛出异常 - **`orElse(T other)`**:返回 `Optional` 中包装的值,如果值不存在,则返回指定的默认值。 - **`orElseGet(Supplier<? extends T> other)`**:与 `orElse` 类似,但默认值是通过 `Supplier` 函数式接口提供的,只有在值不存在时才会计算。 - **`orElseThrow(Supplier<? extends X> exceptionSupplier)`**:返回 `Optional` 中的值,如果不存在,则抛出指定的异常 [^1]。 ### Optional 的最佳实践 #### 避免直接使用 `get()` 在没有确认 `Optional` 是否包含值的情况下,直接调用 `get()` 方法是非常危险的,因为它可能会抛出 `NoSuchElementException`。因此,在调用 `get()` 之前,应始终使用 `isPresent()` 或 `ifPresent()` 来检查值是否存在 。 #### 使用 `orElse` 和 `orElseGet` 提供默认值 当需要处理可能为空的情况时,`orElse` 和 `orElseGet` 是非常有用的工具。`orElseGet` 特别适合在默认值需要复杂计算时使用,因为它只在必要时才执行计算 [^1]。 #### 使用 `map` 和 `flatMap` 进行链式调用 `Optional` 支持 `map` 和 `flatMap` 方法,允许对值进行转换而不必显式地进行空值检查。例如,在处理嵌套对象时,可以使用 `flatMap` 来简化代码 [^3]。 #### 示例代码 ```java public Result<TaskInfoVo> getTaskInfo(String taskId) { TaskNode taskNode = taskExecutor.getByTaskId(taskId); TaskInfoVo taskInfoVo = TaskInfoVo.builder() .taskName(taskNode.getName()) .finishTime(Optional.ofNullable(taskNode.getFinishTime()) .map(date -> date.getTime()) .orElse(null)) .user(taskNode.getUser()) .memo(taskNode.getMemo()) .build(); return Result.ok(taskInfoVo); } ``` 在这个例子中,`Optional.ofNullable` 被用来处理 `taskNode.getFinishTime()` 可能为 `null` 的情况。通过 `map` 方法,可以安全地将日期转换为时间戳,而无需担心空指针异常 [^3]。 #### 减少 `if (obj == null)` 检查 通过合理使用 `Optional`,可以减少代码中大量的 `if (obj == null)` 检查,使代码更加简洁和易读。特别是在与外部世界(如数据库查询、REST 端点等)交互时,`Optional` 可以帮助更好地管理空值 [^4]。 #### 避免过度使用 `Optional` 尽管 `Optional` 提供了许多便利,但过度使用它也可能导致代码变得难以理解和维护。因此,在决定是否使用 `Optional` 时,应权衡其利弊,并确保团队成员都理解其用途和用法 [^1]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值