Java 8新特性:Optional类
Java 8新特性:Optional类
在上一篇介绍Stream流式数据处理的文章中提到了Optional
类,这是Java 8新增的一个类,用以解决程序中常见的NullPointerException
异常问题。本篇文章将详细介绍Optional
类,以及如何用它消除代码中的null
检查。
避免使用null
检查
作为Java开发人员,几乎所有人都遇到过NullPointerException
异常,大多数人遇到NullPointerException
异常时都会在异常出现的地方加上if
代码块来判断值不为空,比如下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
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
逻辑判断中,也许下面的代码看起来可读性稍好一些:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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
对象:
1 |
Optional<String> emptyOpt = Optional.empty(); |
empty()
方法创建的对象没有值,如果对emptyOpt
变量调用isPresent()
方法会返回false
,调用get()
方法抛出NullPointerException
异常。
of()
方法使用一个非空的值创建Optional
对象:
1 2 |
String str = "Hello World"; Optional<String> notNullOpt = Optional.of(str); |
ofNullable()
方法接收一个可以为null
的值:
1 |
Optional<String> nullableOpt = Optional.ofNullable(str); |
如果str
的值为null
,得到的nullableOpt
是一个没有值的Optional
对象。
提取Optional
对象中的值
如果我们要获取User
对象中的roleId
属性值,常见的方式是直接获取:
1 2 3 4 |
String roleId = null; if (user != null) {roleId = user.getRoleId(); } |
使用Optional
中提供的map()
方法可以以更简单的方式实现:
1 2 |
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
异常,区别在于该方法可以指定抛出的异常类型。
下面来看看这三个方法的具体用法:
1 2 3 4 5 6 |
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>
函数式接口,一般用于将信息打印到控制台:
1 2 |
Optional<String> strOpt = Optional.of("Hello World"); strOpt.ifPresent(System.out::println); |
使用filter()
方法过滤
filter()
方法可用于判断Optional
对象是否满足给定条件,一般用于条件过滤:
1 2 |
Optional<String> optional = Optional.of("lw900925@163.com"); optional = optional.filter(str -> str.contains("164")); |
在上面的代码中,如果filter()
方法中的Lambda表达式成立,filter()
方法会返回当前Optional
对象值,否则,返回一个值为空的Optional
对象。
如何正确使用Optional
通过上面的例子可以看出,Optional
类可以优雅的避免NullPointerException
带来的各种问题,不过,你是否真正掌握了Optional
的用法?假设你试图使用Optional
来避免可能出现的NullPointerException
异常,编写了如下代码:
1 2 3 4 5 6 7 |
Optional<User> userOpt = Optional.ofNullable(user); if (userOpt.isPresent()) {User user = userOpt.get();// do something... } else {// do something... } |
坦白说,上面的代码与我们之前的使用if
语句判断空值没有任何区别,没有起到Optional
的正真作用:
1 2 3 4 5 |
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()
方法,比如:
1 2 3 4 5 6 7 8 |
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()
方法的使用
1 |
return str != null ? str : "Hello World" |
上面的代码表示判断字符串str
是否为空,不为空就返回,否则,返回一个常量。使用Optional
类可以表示为:
1 |
return strOpt.orElse("Hello World") |
简化if-else
1 2 3 4 5 6 7 8 9 10 11 |
User user = ... if (user != null) {String userName = user.getUserName();if (userName != null) {return userName.toUpperCase();} else {return null;} } else {return null; } |
上面的代码可以简化成:
1 2 3 4 5 6 |
User user = ... Optional<User> userOpt = Optional.ofNullable(user);return userOpt.map(User::getUserName).map(String::toUpperCase).orElse(null); |
总结一下,新的Optional
类让我们可以以函数式编程的方式处理null
值,抛弃了Java 8之前需要嵌套大量if-else
代码块,使代码可读性有了很大的提高。
Java 8新特性:Optional类相关推荐
- Java JDK8新特性Optional类
Optional类 1.该类java.util包下,是不能被继承的泛型类即:public final class Optional<T>. 2.该类有两个私有属性: T value和 静态 ...
- Java 8 新特性 Optional 类学习,理解并应用。NullPointerException空值检测
- JDK8新特性-Optional类
个人简介 作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门. 文章目录 个人简介 JDK8新特性-Option ...
- java 8 optional 类,Java8新特性-Optional类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念.并且可以避免空指 ...
- Java8新特性——Optional 类
文章目录 前言 Optional 类 1.概述 2.API介绍 of ofNullable empty isPresent get ifPresent orElse orElseGet orElseT ...
- Java8新特性 Optional类
作为开发人员每天与NullPointerException斗智斗勇.每接收到参数或调用方法获得值得判断一下是否为null.稍不留意,空指针异常就像幽灵一样出现了.这篇文章我们来学习Java8是如何通过 ...
- Java8新特性Optional类
这里写自定义目录标题 Java8 Optional 类 前言 创建 Optional 实例 Optional API常用接口的用法 get()方法 isPresent()方法 isPresent()方 ...
- JDK8新特性 - Optional类
引言 Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException).本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空 ...
- Java8新特性-Optional类
概念:Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这 ...
- Java 8 新特性 Stream类的collect方法
1.Collectors.toList():转换成List集合./ Collectors.toSet():转换成set集合. System.out.println(Stream.of("a& ...
最新文章
- Building Android App Without an IDE
- switch java 语法_Java编程—switch语句语法详解
- OSPF的LSA类型 ——连载五自治系统外部的LSA
- 【CLion】如何编译运行单个文件 (C/C++ Single File Execution插件的使用)
- 服务器主板点不亮排查
- Python与C++动态链接库交互 win10平台
- GIT 添加多个git账号
- 程序员专属段子集锦 4/10
- socket和URLConnection
- 用代码初始化APP的window
- 李宏毅机器学习——无监督学习(三)
- 手把手,从零开始搭建个人博客网站(附源码)
- xp系统从u盘启动计算机,联想xp系统如何设置U盘启动_联想xp通过bios设置U盘启动的步骤...
- 基于HAL库的stm32F7串口通信
- github账户登录ArcGIS developer并申请API key
- 直入樱花深处,静待落英满襟
- 车辆计数“FCN-rLSTM: Deep Spatio-Temporal Neural Networks for Vehicle Counting in City Cameras”
- 梯度提升树(GBDT)
- 企业wifi管家——让天下没有难管的wifi
- 2016即将结束,你的目标实现了吗?