Java中关于Optional的 orElse 操纵,以及 orElse 与 orElseGet 的区别 ...

打印 上一主题 下一主题

主题 1023|帖子 1023|积分 3073

1. 大概说明

这篇文章的目的是为了说明:


  • orElse 怎样利用
  • orElseGet 怎样利用
  • 两者的区别
备注:orElse 大概导致 NullPointerException,当 orElse 的参数是间接计算得来的时候。虽然这种说法有点牵强(因为并不是orElse导致了空指针异常),但是利用 orElseGet 确实可以避免这种情况。
2. 详细分析

2.1 .orElse 操纵

   先看个例子:
  1. Optional<String> optional = Optional.empty();
  2. System.out.println(optional.isPresent); // ---->输出:false
  3. // 返回 false,表示 Optional 里没有值。
复制代码
剖析:
  

  • Optional.empty() 代表 一个空的 Optional 实例,即 Optional 没有值
  • Optional.ofNullable(null) 等价于 Optional.empty()。
  2.2 .orElse 的作用:避免空指针异常



  • 如果 Optional 为空(即 Optional.empty()),就返回 orElse() 里提供的默认值。
  • 如果 Optional 有值,就直接返回这个值,不执行 orElse() 提供的默认值。
注意:不管 Optional 为不为空,这个值都会创建,只不过为空时,才利用
  1. // 举例:当Optional为空时,orElse()才会触发
  2. String result = Optional.ofNullable(null)
  3.     .orElse("默认值");
  4. System.out.println(result); // ---->输出:默认值
复制代码
  1. // 再举个例子:
  2. Map<Long, List<String>> map = new HashMap<>();
  3. map.put(1L, Arrays.asList("A", "B", "C"));
  4. List<String> result = Optional.ofNullable(map.get(1L))
  5.     .orElse(Collections.emptyList()); // 为null就返回 空列表
  6. System.out.println(result);  // ---->输出:[A, B, C] (orElse() 没起作用)
复制代码
2.3 为什么要用?

  1. List<String> result = Optional.ofNullable(map.get(0L))
  2.     .orElse(Collections.emptyList())
  3.     .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 computedResult },即入参为空,有返回值(任意类型的)
  • 仅当 Optional 为空时才会执行 supplier.get(),不会提前创建默认值
  • 实用于默认值创建代价较高的情况
看个例子:
  1. class User {
  2.     // 中文名
  3.         private String chineseName;
  4.         // 英文名
  5.         private EnglishName englishName;
  6. }
  7. class EnglishName {
  8.     // 全名
  9.     private String fullName;
  10.     // 简写
  11.     private String shortName;
  12. }
复制代码
如果我们现在有 User 类,用户注册账号时,需要提供自己的中文名或英文名,或都提供,我们抽象出一个EnglishName 类,它包罗英文名的全名和简写(因为有的英文名确实太长了)。现在,我们希望有一个User.getName() 方法,它可以像下面如许实现:
  1. class User {
  2.     // ... 之前的内容
  3.     public String getName1() {
  4.         return Optional.ofNullable(chineseName)
  5.                 .orElse(englishName.getShortName());
  6.     }
  7.    
  8.     public String getName2() {
  9.         return Optional.ofNullable(chineseName)
  10.                 .orElseGet(() -> englishName.getShortName());
  11.     }
  12. }
复制代码
写了两个版本,分别利用 orElse 和 orElseGet。现在,你可以看出 getName1() 方法有什么风险了吗?它会出现空指针异常吗?----> 是的。当用户只提供了中文名时,此时 englishName 属性是 null,但是在 orElse 中,englishName.getShortName()总是会执行。而在 getName2() 中,这个风险却没有。
再举个例子:
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         System.out.println("orElse() 的情况:");
  4.         String result1 = Optional.ofNullable("实际值")
  5.             .orElse(test2());
  6.         System.out.println("最终结果: " + result1);
  7.         System.out.println("orElseGet() 的情况:");
  8.         String result2 = Optional.ofNullable("实际值")
  9.             .orElseGet(() -> test2());
  10.         System.out.println("最终结果: " + result2);
  11.     }
  12.     public static String test2() {
  13.         System.out.println("执行昂贵的计算...");
  14.         return "昂贵默认值";
  15.     }
  16. }
复制代码
输出:
  1. orElse() 的情况:
  2. 执行昂贵的计算...
  3. 最终结果: 实际值
  4. orElseGet() 的情况:
  5. 最终结果: 实际值
复制代码
  至此,文章结束,记得点赞收藏评论!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表