题记:不到最后时刻,千万别轻言放弃,无论结局成功与否,只要你拼博过,尽力过,一切问心无愧


Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。

Optional类是Java8为了解决null值判断问题,借鉴google guava类库的Optional类而引入的一个同名Optional类,本文将讲述Optional类的使用与常用方法概述。

** 你可能需要
CSDN 网易云课堂教程
掘金 EDU学院教程
知乎 Flutter系列文章

1 为什么要设计Optional?

在 Java 开发中,通常会使用 if-else 逻辑判断来解决 NullPointerException 问题,当有对象模型嵌套过多时,就会因过多的 if-else 判断而形成代码累赘。

使用Optional类可以避免显式的null值判断(null的防御性检查),避免因过多的 if-else 判断而形成的代码累赘。

通过使用 Optional 可减少代码中的判空,实现函数式编程。

2 Optional 的基本使用

一个实际的应用场景就是需要获取用户的地区 ID 信息,传统的获取方法如下代码清单2-1所示:

//代码清单 2-1
//获取用户的地区 code
publish String getUserCountryCode(UserInfor user){String countryCode = "";if (user != null) {Address address = user.getAddress();if (address != null) {Country country = address.getCountry();if (country != null) {String code = country.getCountryCode();if (code != null) {countryCode = code.toUpperCase();}}}}return countryCode ;
}

代码清单 2-1 通过 if-else 重重校验可避免在调用过程中因某个对象为 null 而导致的 NullPointerException ,通过 Optional 类的函数式编程来实现同样的效果 如下代码清单 2-2所示 :

  // 代码清单 2-2public String getUserCountryCodByOptional(UserInfor user) {return Optional.ofNullable(user).map(c -> c.getAddress()).map(r -> r.getCountry()).map(u -> u.getCountryCode()).orElseThrow(() -> new IllegalArgumentException(" 无法获取到新的值")).toUpperCase();}

Tips
双冒号:与 箭头函数->,是Java8的lambda表达式,就是匿名函数,如下代码清单 2-3中的使用。

 // 代码清单 2-3public  void test(){///新建集合List<String> list = new ArrayList();///模拟数据for (int i = 0; i < 10; i++) {list.add("测试数据 "+i);}//第一种 for循环for (int i = 0; i < list.size(); i++) {//获取到 list 中对应索引的值String s = list.get(i);}//第二种 增强forfor (String  s: list) {//s 即为获取到的list中的值}//第三种 使用lambda表达式以及函数操作符 ->list.forEach((s) -> System.out.println(s));//第四种 Java8中使用双冒号::操作符完成list.forEach(System.out::println);}

在 代码清单 2-2中所求的效果也可以使用 双冒号来实现,如下代码清单 2-4 所示:

  // 代码清单 2-4public String getUserCountryCodByOptional2(UserInfor user) {return Optional.ofNullable(user).map(UserInfor::getAddress).map(Address::getCountry).map(Country::getCountryCode).orElseThrow(() -> new IllegalArgumentException(" 无法获取到新的值")).toUpperCase();}

3 Optional 的简述

在上述代码清单中通Optional的使用,很优雅的达到函数式编程效果,现有总结以下结论。

3.1 Optional 对象创建

在使用 Optional 时首先要创建 Optional 对象,Optional类的两个构造方法都是private型的,因此类外部不能显示的使用new Optional()的方式来创建Optional对象。

可通过Optional类提供的三个静态方法empty()、of(T value)、ofNullable(T value)来创建Optinal对象,示例如下

    // 第一种 创建一个包装对象值为空的Optional对象 一般不使用Optional<String> optStr = Optional.empty();// 第二种 创建包装对象值非空的Optional对象Optional<String> optStr1 = Optional.of("optional");// 第三种 创建包装对象值允许为空的Optional对象Optional<String> optStr2 = Optional.ofNullable(null);

第二种方式 通过 of 方法为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

第三种方式 ofNullable 为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

3.2 map 、flatMap 、filter

Optional 的 map 方法用来获取 Optional 中的值,Optional 也提供了 get方法来获取其中的值。
Optional 的 map 方法调用,Optional 如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。

简单的描述就是通过map方法从Optional对象中提取和转换值。

  public void testMap(){// 第二种 创建包装对象值非空的Optional对象Optional<String> optStr1 = Optional.of(" 测试 map 方法数据");///获取 optStr1 中的值Optional<String> stringOptional = optStr1.map((value) -> value);///optStr1 有值 所以输出的是  optionalSystem.out.println(stringOptional.orElse("orElse输出的内容"));}

单元测试效果如下图所示

flatMap方法与map方法类似,区别在于mapping函数的返回值不同。map方法的mapping函数返回值可以是任何类型T,而flatMap方法的mapping函数必须是Optional,目前笔者还没有应用到实际业务场景中。

filter 方法中如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。

3.3 orElse、orElseGet、orElseThrow方法

orElse方法,对应的 Optional 如果有值则将其返回,否则返回指定的其它值。

orElseGet与orElse方法类似,区别在于得到的默认值,orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值 。

orElseThrow如果有值则将其返回,否则抛出supplier接口创建的异常,在orElseThrow中我们可以传入一个lambda表达式或方法,如果值不存在来抛出异常。

  public void testOrElse(){// 第一种 创建一个包装对象值为空的Optional对象Optional<String> optStr = Optional.empty();//optStr 无值 所以输出的是 orElse中的内容 "测试 orelse  "//orElse 方法接收的参数是字符串System.out.println("测试1  "+optStr.orElse("测试 orelse  "));// orElseGet 方法接收的是一个函数方法System.out.println("测试2  "+optStr.orElseGet(()->"测试 orElseGet  "));// orElseGet 方法接收的是一个函数方法 返回值是一个 ThrowableSystem.out.println("测试3  "+optStr.orElseThrow(()-> new IllegalArgumentException("空值")));// 第二种 创建包装对象值非空的Optional对象Optional<String> optStr1 = Optional.of("optional");///optStr1 有值 所以输出的是  optionalSystem.out.println(optStr1.orElse("orElse输出的内容"));}

单元测试效果如下图所示:

4 其他

Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。

4.1 or 方法

or 方法,如果值存在,返回 Optional 指定的值,否则返回一个预设的值。

4.2 stream 方法

stream 方法的作用就是将 Optional 转为一个 Stream,如果该 Optional 中包含值,那么就返回包含这个值的 Stream,否则返回一个空的 Stream。

4.3 ifPresentOrElse 方法

在 java8 中,使用 ifPresent 方法来替代传统的 if(user != null)判断,未提供支持 if (user != null) else { // xxx}的操作,也就是在Java8中Optional 类 ifPresent 方法没有对else的操作提供支持。

在java9 中 ifPresentOrElse 方法就相当于是 if (user != null) else { // xxx}的操作。

public void test(UserInfor user) {Optional.ofNullable(user).ifPresentOrElse(u -> {//当user 不为 null 时执行这里user.getName();user.getAge();}, () -> {//当user 为null 时执行这里System.err.println("user 对象为null");});
}

Java Optional的使用实践概述相关推荐

  1. java Optional操作

    目录 Optional对象的创建 isPresent()和isEmpty()判空处理 ifPresent()和ifPresentOrElse()的条件动作 Optional对象中获取值 orElse( ...

  2. Java Optional容器判空处理

    Java Optional容器判空处理 1. Java判空概述 2. Java判空方式 2.1 普通判空方式 2.2 Optional判空方式 1. Java判空概述 Java判空方式有很多多,可以i ...

  3. java查询枚举_查找Java枚举的最佳实践

    查找Java枚举的最佳实践 我们有一个REST API,客户端可以在其中提供表示Java Enums中服务器上定义的值的参数. 因此,我们可以提供一个描述性错误,我们将此valueOf(..)方法添加 ...

  4. 编写高性能Java代码的最佳实践

    编写高性能Java代码的最佳实践 摘要:本文首先介绍了负载测试.基于APM工具的应用程序和服务器监控,随后介绍了编写高性能Java代码的一些最佳实践.最后研究了JVM特定的调优技巧.数据库端的优化和架 ...

  5. MIT Graph实践概述

    MIT Graph实践概述 Features功能 • iCloud Support • Multi Local & Cloud Graphs • Thread Safe • Store Any ...

  6. 《编译与反编译技术实战》——第2章编译器实践概述

    本节书摘来自华章社区<编译与反编译技术实战>一书中的第2章编译器实践概述,作者刘晓楠 陶红伟 岳 峰 戴超,更多章节内容可以访问云栖社区"华章社区"公众号查看 第2章 ...

  7. Java Bean Validation 最佳实践

    <h1 class="postTitle"><a id="cb_post_title_url" class="postTitle2& ...

  8. JVM内存管理------JAVA语言的内存管理概述

    转载自  JVM内存管理------JAVA语言的内存管理概述 引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上 ...

  9. java 8入门与实践_30个Java入门技巧和最佳实践

    java 8入门与实践 Java是最流行的编程语言之一-无论是Win应用程序,Web应用程序,移动,网络,消费电子产品,机顶盒设备,Java随处可见. 在Java上运行的设备超过30亿. 据Oracl ...

最新文章

  1. pytorch torch.norm(input, p=2) → float、torch.norm(input, p, dim, out=None) → Tensor(求范数)
  2. el-drawer点击的时候为什么有边框_别再纠结背景墙边框的材料,这4种线条边框便宜又实用,简洁大方...
  3. LOL手游超燃测试好评如潮,没拿到资格不用急,期待一手不删档
  4. 华尔街英语学习软件_华尔街英语核心课程功能升级 让学员学习之旅更高效
  5. 5部适合学英语的动画电影,快和孩子一起看!
  6. 渗透测试入门15之常见端口安全测试
  7. capjoint一些生成文件的解释
  8. 【原创】.NET读写Excel工具Spire.Xls使用(5)重量级的Excel图表功能
  9. 关于php聊天室的实现方法,PHP聊天室简单实现
  10. Win10如何设置护眼模式?
  11. 【Code】8位编程语言的创始人,你知道几位?
  12. 2018年国考行测错题集(省级)
  13. Java SimpleDateFormat.setLenient(boolean lenient)方法使用
  14. etc的常见算法_几个常用算法的适应场景及其优缺点(非常好)
  15. 这所“南方小镇”藏着雅居乐陈卓林描绘的“第二人生”
  16. 【 SAP消息号BS013】
  17. 快速解读Nor Flash Datasheet
  18. Hadoop生态系统官网、下载地址、文档
  19. 如何看linux是arm还是amd_如何确定真性分手还是假性分手?看这六个判断标准
  20. 超链接 a href 提交表单通过post方式

热门文章

  1. 百度AI快车道深圳专场,揭秘CV目标检测核心技术
  2. 医疗设备-监护仪-数据解析(协议、通信)
  3. 计算机视觉论文-2021-07-05
  4. 计算机视觉论文-2021-06-23
  5. 超赞!arXiv论文如何一键链接解读视频,这个浏览器扩展帮你实现
  6. MIT“35岁以下科技创新35人”榜单揭晓
  7. 2019年财政收支分析_2019年模锻行业经济运行情况分析
  8. TensorFlow官方教程翻译:TensorFlow调试器
  9. 更新版 | GPU CUDA 进阶课程
  10. ROS MATLAB 启动