今天分享的事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(); // 可能返回 null
Optional<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():空值时返回默认值 0
BigDecimal 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