点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试文章

作者:一书生VOID

lw900925.github.io/java/java8-optional.html

Optional类是Java 8新增的一个类,用以解决程序中常见的NullPointerException异常问题。本篇文章将详细介绍Optional类,以及如何用它消除代码中的null检查。

避免使用null检查

作为Java开发人员,几乎所有人都遇到过NullPointerException异常,大多数人遇到NullPointerException异常时都会在异常出现的地方加上if代码块来判断值不为空,比如下面的代码:

public void bindUserToRole(User user) {if (user != null) {String roleId = user.getRoleId();if (roleId != null) {Role role = roleDao.findOne(roleId);if (role != null) {role.setUserId(user.getUserId());roleDao.save(role);}}}
}

这是比较普遍的做法,为了避免出现NullPointerException异常,手动对可能为null值进行了处理,不过代码看起来非常糟糕,业务逻辑被淹没在if逻辑判断中,也许下面的代码看起来可读性稍好一些:

public String bindUserToRole(User user) {if (user == null) {return;}String roleId = user.getRoleId();if (roleId == null) {return;}Role = roleDao.findOne(roleId);if (role != null) {role.setUserId(user.getUserId());roleDao.save(role);}
}

上面的代码避免了深层的if语句嵌套,但本质上是一样的,方法内有三个不同的返回点,出错后调试也不容易,因为你不知道是那个值导致了NullPointerException异常。

基于上面的原因,Java 8中引入了一个新的类Optional,用以避免使用null值引发的种种问题。扩展:如何更优雅的处理空值?

Optional类

java.util.Optional<T>类是一个封装了Optional值的容器对象,Optional值可以为null,如果值存在,调用isPresent()方法返回true,调用get()方法可以获取值。

创建Optional对象

Optional类提供类三个方法用于实例化一个Optional对象,它们分别为empty()、of()、ofNullable(),这三个方法都是静态方法,可以直接调用。

empty()方法用于创建一个没有值的Optional对象:

Optional<String> emptyOpt = Optional.empty();

empty()方法创建的对象没有值,如果对emptyOpt变量调用isPresent()方法会返回false,调用get()方法抛出NullPointerException异常。

of()方法使用一个非空的值创建Optional对象:

String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);

ofNullable()方法接收一个可以为null的值:

Optional<String> nullableOpt = Optional.ofNullable(str);

如果str的值为null,得到的nullableOpt是一个没有值的Optional对象。

提取Optional对象中的值

如果我们要获取User对象中的roleId属性值,常见的方式是直接获取:

String roleId = null;
if (user != null) {roleId = user.getRoleId();
}

使用Optional中提供的map()方法可以以更简单的方式实现:

Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);

使用orElse()方法获取值

Optional类还包含其他方法用于获取值,这些方法分别为:

  • orElse():如果有值就返回,否则返回一个给定的值作为默认值;

  • orElseGet():与orElse()方法作用类似,区别在于生成默认值的方式不同。该方法接受一个Supplier<? extends T>函数式接口参数,用于生成默认值;

  • orElseThrow():与前面介绍的get()方法类似,当值为null时调用这两个方法都会抛出NullPointerException异常,区别在于该方法可以指定抛出的异常类型。

下面来看看这三个方法的具体用法:

String str = "Hello World";
Optional<String> strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello Shanghai");
String orElseGet = strOpt.orElseGet(() -> "Hello Shanghai");
String orElseThrow = strOpt.orElseThrow(() -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

此外,Optional类还提供了一个ifPresent()方法,该方法接收一个Consumer<? super T>函数式接口,一般用于将信息打印到控制台:

Optional<String> strOpt = Optional.of("Hello World");
strOpt.ifPresent(System.out::println);

使用filter()方法过滤

filter()方法可用于判断Optional对象是否满足给定条件,一般用于条件过滤:

Optional<String> optional = Optional.of("lw900925@163.com");
optional = optional.filter(str -> str.contains("164"));

在上面的代码中,如果filter()方法中的Lambda表达式成立,filter()方法会返回当前Optional对象值,否则,返回一个值为空的Optional对象。Java知音公众号内回复“后端面试”,送你一份Java面试题宝典。

如何正确使用Optional

通过上面的例子可以看出,Optional类可以优雅的避免NullPointerException带来的各种问题,不过,你是否真正掌握了Optional的用法?

假设你试图使用Optional来避免可能出现的NullPointerException异常,编写了如下代码:

Optional<User> userOpt = Optional.ofNullable(user);
if (userOpt.isPresent()) {User user = userOpt.get();// do something...
} else {// do something...
}

坦白说,上面的代码与我们之前的使用if语句判断空值没有任何区别,没有起到Optional的正真作用:

if (user != null) {// do something...
} else {// do something...
}

当我们从之前版本切换到Java 8的时候,不应该还按照之前的思维方式处理null值,Java 8提倡函数式编程,新增的许多API都可以用函数式编程表示,Optional类也是其中之一。这里有几条关于Optional使用的建议:

  • 尽量避免在程序中直接调用Optional对象的get()和isPresent()方法;

  • 避免使用Optional类型声明实体类的属性;

第一条建议中直接调用get()方法是很危险的做法,如果Optional的值为空,那么毫无疑问会抛出NullPointerException异常,而为了调用get()方法而使用isPresent()方法作为空值检查,这种做法与传统的用if语句块做空值检查没有任何区别。

第二条建议避免使用Optional作为实体类的属性,它在设计的时候就没有考虑过用来作为类的属性,如果你查看Optional的源代码,你会发现它没有实现java.io.Serializable接口,这在某些情况下是很重要的(比如你的项目中使用了某些序列化框架),使用了Optional作为实体类的属性,意味着他们不能被序列化。

下面我们通过一些例子讲解Optional的正确用法:

正确创建Optional对象

上面提到创建Optional对象有三个方法,empty()方法比较简单,没什么特别要说明的。主要是of()和ofNullable()方法。当你很确定一个对象不可能为null的时候,应该使用of()方法,否则,尽可能使用ofNullable()方法,比如:

public static void method(Role role) {// 当Optional的值通过常量获得或者通过关键字new初始化,可以直接使用of()方法Optional<String> strOpt = Optional.of("Hello World");Optional<User> userOpt = Optional.of(new User());// 方法参数中role值不确定是否为null,使用ofNullable()方法创建Optional<Role> roleOpt = Optional.ofNullable(role);
}

orElse()方法的使用

return str != null ? str : "Hello World"

上面的代码表示判断字符串str是否为空,不为空就返回,否则,返回一个常量。使用Optional类可以表示为:

return strOpt.orElse("Hello World")

简化if-else

User user = ...
if (user != null) {String userName = user.getUserName();if (userName != null) {return userName.toUpperCase();} else {return null;}
} else {return null;
}

上面的代码可以简化成:

User user = ...
Optional<User> userOpt = Optional.ofNullable(user);return userOpt.map(User::getUserName).map(String::toUpperCase).orElse(null);

总结一下,新的Optional类让我们可以以函数式编程的方式处理null值,抛弃了Java 8之前需要嵌套大量if-else代码块,使代码可读性有了很大的提高。

热门内容:MyBatis动态SQL(认真看看, 以后写SQL就爽多了)
选型必看:RabbitMQ 七战 Kafka,差异立现为什么阿里规定需要在事务注解@Transactional中指定rollbackFor?最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡

如何正确的使用Java8中的Optional类来消除代码中的null检查相关推荐

  1. 使用Java8中的Optional类来消除代码中的null检查

      作者:一书生VOID lw900925.github.io/java/java8-optional.html Optional类是Java 8新增的一个类,用以解决程序中常见的NullPointe ...

  2. 使用Optional类来消除代码中的null检查

    Python实战社群 Java实战社群 长按识别下方二维码,按需求添加 扫码关注添加客服 进Python社群▲ 扫码关注添加客服 进Java社群▲ 作者丨一书生VOID lw900925.github ...

  3. 消除代码中的坏味道,编写高质量代码

    消除代码中的坏味道,编写高质量代码 Intro 想要写出较好的代码,保证代码的高质量需要时刻警惕代码中的坏味道,今天分享一下,我觉得平时写的代码中可能会出现的坏味道代码的一些示例 常见的坏味道代码 B ...

  4. Java8新特性Optional类

    这里写自定义目录标题 Java8 Optional 类 前言 创建 Optional 实例 Optional API常用接口的用法 get()方法 isPresent()方法 isPresent()方 ...

  5. Java8新特性 Optional类

    作为开发人员每天与NullPointerException斗智斗勇.每接收到参数或调用方法获得值得判断一下是否为null.稍不留意,空指针异常就像幽灵一样出现了.这篇文章我们来学习Java8是如何通过 ...

  6. Java8新特性之Optional类(附代码案例)

    1. 概述 Optional< T >类是要给容器类,它可以保存类型T的值,代表这个值存在.或者仅仅保存null, 表示这个值不存在.原来用null表示一个值不存在,现在Optional可 ...

  7. Java8新特性-Optional类

    概念:Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这 ...

  8. Java8新特性——Optional 类

    文章目录 前言 Optional 类 1.概述 2.API介绍 of ofNullable empty isPresent get ifPresent orElse orElseGet orElseT ...

  9. java 8 optional 类,Java8新特性-Optional类

    Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念.并且可以避免空指 ...

最新文章

  1. L2-004 这是二叉搜索树吗?-团体程序设计天梯赛GPLT
  2. postgresql后期给开发建表的权限问题
  3. 别等了,全面「远程办公」凉了
  4. linux 一切都是文件_一切都是文件
  5. Learning-MySQL【4】:表的操作管理和 MySQL 的约束控制
  6. java 关闭对话框_java等待关闭对话框
  7. sessionStrorage + localStorage+ cookes
  8. 小米个性主题显示服务器不可用,MIUI个性主题上线透明壁纸功能,并修复状态栏无法混搭问题!...
  9. Meshlab模型对齐
  10. 高项 人力资源管理论文
  11. 无缝拼接文件 copy/b 使用
  12. vob文件如何转换成mp4
  13. 基于FPGA的密码锁
  14. APS计划排程系统和生产排产系统,需要哪些基础资料(一)
  15. 运用awk提取日志文件中的IP地址
  16. wireshark抓包实验 分析 详解
  17. 2022强国杯初赛部分题目
  18. CORBA_百度百科
  19. KVM切换器和VGA切换器的区别
  20. 程序员的三大优点:懒惰、急躁和傲慢

热门文章

  1. HDU(1847)Good Luck in CET-4 Everybody!
  2. platform_driver_register适配的两种方式及probe是否启动与硬件关系
  3. [Unity3D]Unity3D连衣裙实现游戏开发系统
  4. 凌亮:动手学数据分析笔记
  5. 中国电子学会图形化四级编程题:加减法混合运算器
  6. 刻意练习:LeetCode实战 -- Task27.分发饼干
  7. 技术图文:如何利用C# + Echarts 绘制「堆叠条形图」?
  8. 算法基础知识科普:8大搜索算法之二分搜索
  9. 针对2013年B题碎纸片拼接问题(附件一、附件二)
  10. 赠书福利 | Tidio AI 趋势报告:约42%受访者能够接受机器人伴侣