Java中Optional的orElse操作及orElse与orElseGet的区别详解
目录
- 1. 大概说明
- 2. 详细分析
- 2.1 .orElse 操作
- 2.2 .orElse 的作用:避免空指针异常
- 2.3 为什么要用?
- 2.4 orElseGet如何使用
- 2.5 orElse和orElseGet的区js别
- 总结
1. 大概说明
这篇文章的目的是为了说明:
- orElse 如何使用
- orElseGet 如何使用
- 两者的区别
备注:orElse 可能导致 NullPointerException,当 orElse 的参数是间接计算得来的时候。虽然这种说法有点牵强(因为并不是orElse导致了空指针异常),但是使用 orElseGet 确实可以避免这种情况。
2. 详细分析
2FUFsRwovZd.1 .orElse 操作
先看个例子:
Optional<String> optional = Optional.empty(); System.out.println(optional.isPresent); // ---->输出:false // 返回 false,表示 Optional 里没有值。解析:
Optional.empty()
代表 一个空的 Optional 实例,即Optional
没有值。Optional.ofNullable(null)
等价于Optional.empty()
。
2.2 .orElse 的作用:避免空指针异常
- 如果
Optional
为空(即Optional.empty()
),就返回orElse()
里提供的默认值。 - 如果
Optional
有值,就直接返回这个值,不执行orElse()
提供的默认值。
注意:不管 Optional 为不为空,这个值都会创建,只不过为空时,才使用
// 举例:当Optional为空时,orE编程客栈lse()才会触发 String result = Optional.ofNullable(null) .orElse("默认值"); System.out.println(result); // ---->输出:默认值
// 再举个例子: Map<Long, List<String>> map = new HashMap<>(); map.put(1L, Arrays.asList("A", "B", "C")); List<String> result = Optional.ofNullable(map.get(1L)) .orElse(Collections.emptyList()); // 为null就返回 空列表 System.out.println(result); // ---->输出:[A, B, C] (orElse() 没起作用)
2.3 为什么要用?
List<String> result = Optional.ofNullable(map.get(0L)) .orElse(Collections.emptyList()) .stream();
如果 map.get(0L) == null
,那么:
- 不加
.orElse(Collections.emptyList())
→.stream()
会报NullPointerException
❌ - 加了
.orElse(Collections.emptyList())
→.stream()
能正常执行 ✅
2.4 orElseGet如何使用
再来看看 orElseGet 中如何使用:
orElseGet 作用:获取数据并且设置数据为空时的默认值。如果数据不为空就能获取到该数据;如果为空则返回传入的参数来创建对象。
具体的使用案例可看下图:
2.5 orElse和orElseGet的区别
orElse()
和 orElseGet()
都是Optional
类中的方法,用于在 Optional
为空时提供默认值。但它们的区别在于 默认值的获取方式:
1、orElse(T other)
- 直接传递一个默认值
- 即使
Optional
里有值,也会创建 other 对象,但不会使用它 - 适用于默认值创建代价较低的情况
2、orElseGet(Supplier<? extends T> supplier)
- 传递的是一个
Supplier
(懒加载:只有需要的时候才会创建)接口,它是一个函数式接口,形式是这样的:()->{ return cFUFsRwovZdomputedResult }
,即入参为空,有返回值(任意类型的) - 仅当
Optional
为空时才会执行supplier.get()
,不会提前创建默认值 - 适用于默认值创建代价较高的情况
看个例子:
class User { // 中文名 private String chineseName; // 英文名 private EnglishName englishName; } class EnglishName { // 全名 private String fullName; js// 简写 private String shortName; }
假如我们现在有 User 类,用户注册账号时,需要提供自己的中文名或英文名,或都提供,我们抽象出一个EnglishName 类,它包含英文名的全名和简写(因为有的英文名确实太长了)。现在,我们希望有一个User.getName()
方法,它可以像下面这样实现:
class User { // ... 之前的内容 public String getName1() { return Optional.ofNullable(chineseName) .orElse(englishName.getShortName()); } public String getName2() { return Optional.ofNullable(chineseName) .orElseGet(() -> englishName.getShortName()); } }
写了两个版本,分别使用 orElse 和 orElseGet。现在,你可以看出 getName1()
方法有什么风险了吗?它会出现空指针异常吗?----> 是的。当用户只提供了中文名时,此时 englishName
属性是 null,但是在 orElse 中,englishName.getShortName()
总是会执行。而在 getName2()
中,这个风险却没有。
再举个例子:
public class Test { public static void main(String[] args) { System.out.println("orElse() 的情况:"); String result1 = Optional.ofNullable("实际值") .orElse(test2()); System.out.println("最终结果: " + result1); System.out.println("orElseGet() 的情况:"); String result2 = Optional.ofNullable("实际值") .orElseGet(() -> test2()); System.out.println("最终结果: " + result2); } public static String test2() { System.out.println("执行昂贵的计算..."); return "昂贵默认值"; } }
输出:
orElse() 的情况:
执行昂贵的计算...最终结果: 实际值orElseGet() 的情况:
最终结果: 实际值
总结
到此这篇关于Java中Optional的orElse操作及orElse与orElseGet区别详解的文章就介绍到这了,更多相关Java Optional的orElse操作内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论