Java8新特性之五:Optional

时间:2022-09-22 20:00:47

  NullPointerException相信每个JAVA程序员都不陌生,是JAVA应用程序中最常见的异常。之前,Google Guava项目曾提出用Optional类来包装对象从而解决NullPointerException。受此影响,JDK8的类中也引入了Optional类,在新版的SpringData Jpa和Spring Redis Data中都已实现了对该方法的支持。

1、Optional类

 /**
* A container object which may or may not contain a non-null value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
*
* @since 1.8
*/
public final class Optional<T> {
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>(); /**
* If non-null, the value; if null, indicates no value is present
*/
private final T value; // 其他省略
}

  该方法的注释大致意思是:Optional是一个容器对象,它可能包含空值,也可能包含非空值。当属性value被设置时,isPesent()方法将返回true,并且get()方法将返回这个值。

  该类支持泛型,即其属性value可以是任何对象的实例。

2、Optional类的方法

    序号    

方法

方法说明
1
private Optional()
 无参构造,构造一个空Optional
2
private Optional(T value)
 根据传入的非空value构建Optional
3
public static<T> Optional<T> empty()
返回一个空的Optional,该实例的value为空
4
public static <T> Optional<T> of(T value)
根据传入的非空value构建Optional,与Optional(T value)方法作用相同
5
public static <T> Optional<T> ofNullable(T value)

与of(T value)方法不同的是,ofNullable(T value)允许你传入一个空的value,

当传入的是空值时其创建一个空Optional,当传入的value非空时,与of()作用相同

6
public T get()
 返回Optional的值,如果容器为空,则抛出NoSuchElementException异常
7
public boolean isPresent()
 判断当家Optional是否已设置了值
8
public void ifPresent(Consumer<? super T> consumer)
 判断当家Optional是否已设置了值,如果有值,则调用Consumer函数式接口进行处理
9
public Optional<T> filter(Predicate<? super T> predicate)
 如果设置了值,且满足Predicate的判断条件,则返回该Optional,否则返回一个空的Optional
10
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

如果Optional设置了value,则调用Function对值进行处理,并返回包含处理后值的Optional,否则返回空Optional

11
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
 与map()方法类型,不同的是它的mapper结果已经是一个Optional,不需要再对结果进行包装
12
public T orElse(T other)
 如果Optional值不为空,则返回该值,否则返回other 
13
public T orElseGet(Supplier<? extends T> other)
如果Optional值不为空,则返回该值,否则根据other另外生成一个
14
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
throws X
如果Optional值不为空,则返回该值,否则通过supplier抛出一个异常

3、Optional类的方法举例

  《Java 8 Features Tutorial – The ULTIMATE Guide》中给出了两个简单的例子,我们从这两个例子入手来简单了解一下Optional容器的使用。

  示例一:

 public static void main(String[] args) {
2   Optional< String > fullName = Optional.ofNullable( null );
3   System.out.println( "Full Name is set? " + fullName.isPresent() );
4   System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) );
5   System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
6 }

  运行结果:

Full Name is set? false
Full Name: [none]
Hey Stranger!  

  说明:

  ifPresent()方法当Optional实例的值非空时返回true,否则返回false;

  orElseGet()方法当Optional包含非空值时返回该值,否则通过接收的function生成一个默认的;

  map()方法转换当前Optional的值,并返回一个新的Optional实例;

  orElse()方法与orElseGet方法相似,不同的是orElse()直接返回传入的默认值。

  示例二:修改示例一,使其生成一个非空值的Optional实例

 Optional< String > firstName = Optional.of( "Tom" );
System.out.println( "First Name is set? " + firstName.isPresent() );
System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) );
System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );

  输出结果:

First Name is set? true
First Name: Tom
Hey Tom!

  可以清晰地看出与示例一的区别。这不但简洁了我们的代码,而且使我们的代码更便于阅读。

  下面看一下例子中使用到的几个方法的源码:

  1)、of

 public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}

  2)、isPresent

 public boolean isPresent() {
return value != null;
}

  3)、orElseGet

 public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}

  4)、orElse

 public T orElse(T other) {
return value != null ? value : other;
}

  其他方法源码,读者可以去Optional源码中查看。

4、使用Optional避免空指针

  在我们日常开发过程中不可避免地会遇到空指针问题,在以前,出现空指针问题,我们通常需要进行调试等方式才能最终定位到具体位置,尤其是在分布式系统服务之间的调用,问题更难定位。在使用Optional后,我们可以将接受到的参数对象进行包装,比如,订单服务要调用商品服务的一个接口,并将商品信息通过参数传入,这时候,传入的商品参数可能直接传入的就是null,这时,商品方法可以使用Optional.of(T)对传入的对象进行包装,如果T为空,则会直接抛出空指针异常,我们看到异常信息就能立即知道发生空指针的原因是参数T为空;或者,当传入的参数为空时,我们可以使用Optional.orElse()或Optional.orElseGet()方法生成一个默认的实例,再进行后续的操作。

  下面再看个具体例子:在User类中有个Address类,在Address类中有个Street类,Street类中有streetName属性,现在的需求是:根据传入的User实例,获取对应的streetName,如果User为null或Address为null或Street为null,返回“nothing found”,否则返回对应的streetName。

  实现一:

 @Data
public class User {
private String name;
private Integer age;
private Address address;
}
 @Data
public class Address {
private Street street;
}
 @Data
public class Street {
private String streetName;
private Integer streetNo;
}
 public String getUserSteetName(User user) {

     if(null != user) {

         Address address = user.getAddress();

         if(null != address) {

             Street street = address.getStreet();

             if(null != street) {
return street.getStreetName();
}
}
} return "nothing found";
}

  实现二,使用Optional:

  在实现一中明显的问题是if判断层级太深,下面复用Optional改写:

 @Data
public class User {
private String name;
private Integer age;
private Optional<Address> address = Optional.empty();
}
 @Data
public class Address {
private Optional<Street> street = Optional.empty();
}
 @Data
public class Street {
private String streetName;
private Integer streetNo;
}
 public String getUserSteetName(User user) {

     Optional<User> userOptional = Optional.ofNullable(user);
final String streetName = userOptional.orElse(new User()).getAddress().orElse(new Address()).getStreet().orElse(new Street()).getStreetName();
return StringUtils.isEmpty(streetName) ? "nothing found" : streetName;
}

  利用orElse()方法给定默认值的方式确保不会报空指针问题问题,同时也能实现需求。

Java8新特性之五:Optional的更多相关文章

  1. 乐字节-Java8新特性之Optional

    上一篇小乐带大家了解了Java新特性之Stream,接下来将会继续述说Java新特性之Optional Optional<T>类(java.util.Optional)是一个容器类,代表一 ...

  2. java8新特性之Optional类

    NullPointException可以说是所有java程序员都遇到过的一个异常,虽然java从设计之初就力图让程序员脱离指针的苦海,但是指针确实是实际存在的,而java设计者也只能是让指针在java ...

  3. java8新特性六-Optional 类

    Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. Optional 是个容器:它可以保存类型T的值,或者仅仅保 ...

  4. Java8新特性之Optional,如何优雅地处理空指针

    是什么 ​ 从 Java 8 引入的一个很有趣的特性是 Optional 类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)-- 每个 Java ...

  5. Java8新特性之Optional

    空指针异常一直是困扰Java程序员的问题,也是我们必须要考虑的.当业务代码中充满了if else判断null 的时候程序变得不再优雅,在Java8中提供了Optional类为我们解决NullPoint ...

  6. 乐字节-Java8新特性之Date API

    上一篇文章,小乐给大家带来了Java8新特性之Optional,接下来本文将会给大家介绍Java8新特性之Date API 前言: Java 8通过发布新的Date-Time API来进一步加强对日期 ...

  7. 乐字节-Java8新特性-接口默认方法之Stream流(下)

    接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 ...

  8. Java8新特性之空指针异常的克星Optional类

    Java8新特性系列我们已经介绍了Stream.Lambda表达式.DateTime日期时间处理,最后以"NullPointerException" 的克星Optional类的讲解 ...

  9. Java8 新特性 Optional 类

    Optional 类的简介   Optional类的是来自谷歌Guava的启发,然后就加入到Java8新特性中去了.Optional类主要就是为子决解价值亿万的错误,空指针异常.   Optional ...

随机推荐

  1. 手持设备点击响应速度,鼠标事件与touch事件的那些事

    前言 现在一直在做移动端的开发,这次将单页应用的网页内嵌入了app,于是老大反映了一个问题:app应用点击响应慢!我开始不以为然,于是拿着网页版的试了试,好像确实有一定延迟,于是开始了研究,最后选择了 ...

  2. 如何启动另一个Activity

    --------siwuxie95 首先为res->layout下my_layout.xml 的Design添加一个Button,进入Text, android:text 修改为:启动另一个Ac ...

  3. img标签src不给路径就会出现边框————记一次二笔的编码经历

    <img/>在src加载失败或没有给的,浏览器会自动给img加上边框. 如下图这样: 产品觉得影响美观,一定要pass掉. 原码是这样: .ctn{ position: relative; ...

  4. placeholder属性实现text标签默认值提示用户

    <input type="text" class="searchTxt" id=this.id+"-searchTxt" placeh ...

  5. 用I&sol;O口模拟IIC总线协议遇到的一些问题

    最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...

  6. display&colon;none&semi;与visibility&colon;hidden&semi;的区别

    visibility:隐藏对应的元素但不挤占该元素原来的空间.display:隐藏对应的元素并且挤占该元素原来的空间. 下面来看visibility和dispaly的一些参数 visibility用来 ...

  7. django源码简析——后台程序入口

    这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主要基于django框架,进行项目的开发 ...

  8. tablespace&lpar;表空间&rpar; &sol; segment(断) &sol; extent(盘区)&sol; block(块)&sol;datafile&lpar;文件&rpar;之间的关系

    tablespace(表空间) / segment(断) / extent(盘区)/ block(块)之间的关系   tablespace : 一个数据库划分为一个或多个表逻辑单位,即表空间,每个表空 ...

  9. linux上可代替ftp的工具rz和sz

    对于经常使用Linux系统的人员来说,少不了将本地的文件上传到服务器或者从服务器上下载文件到本地,rz / sz命令很方便的帮我们实现了这个功能,但是很多Linux系统初始并没有这两个命令,因此简单的 ...

  10. nginx 中配置多个location并解决js&sol;css&sol;jpg&sol;等的加载问题

    2017-11-09 22:07 277人阅读 评论(0) 收藏 举报  分类: linux(1)  版权声明:如有版权问题,请私信我. ECS:阿里云 系统:ubuntu 16.04 我的配置文件位 ...