如何使用Java中的Optional

 更新时间:2020年11月30日 10:03:04   作者:West2ers'' Blog  
这篇文章主要介绍了如何使用Java中的Optional,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下

NullPointerException是非常常见的异常。由于它,程序往往需要大量使用if-else代码块来处理空值,这使得代码看起来不简洁 优雅 ,且不方便自己和他人阅读。本文介绍如何用Optional类来处理null值问题。

Optional类

先来看一段代码:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

这段代码在任何一个方法调用时,都有可能抛出NullPointerException
而通常我们的处理方式是不断地利用if代码块来确保上一步的值不为空并执行下一步代码。

if (user != null) {
  Address address = user.getAddress();
  if (address != null) {
    Country country = address.getCountry();
    if (country != null) {
      String isocode = country.getIsocode();
      if (isocode != null) {
        isocode = isocode.toUpperCase();
      }
    }
  }
}

嗯,一股切割器cutter的味道。

Optional类是Java8为了解决null值判断问题,借鉴google guava类库的Optional类而引入的一个同名Optional类,使用Optional类可以避免显式的null值判断(null的防御性检查),避免null导致的NPE(NullPointerException)。

如何创建Optional实例

Optional类没有公共构造函数。 但是确提供了三个静态方法在不同情形下根据需求创建Optional实例。

Optional.of()

这个方法要求你传入一个不为空的值(不一定是引用类型,也可以是原始类型),
所以下面这种写法还是会抛出一个NullPointerException异常:

Optional.of(null);

可见Optional并不能完全避免NullPointerException,关键在于你是否正确以及规范地使用它。
但大多数情况下,我们使用Optional正是由于无法确定值是否为空。在这种情况下,我们使用下面这个方法。

Optional.ofNullable()

这个方法允许你传入空值或者非空值。

Optional.empty()

这个方法会返回一个包装空值的Optional实例。也许你会觉得它会有点鸡肋(我一开始也是这么认为的)。
考虑以下代码:

int dividend = 10, divisor = 0;
int result = dividend / divisor;
Optional<Integer> o = Optional.of(result);

显然它会在运行期抛出ArithmeticException异常,这使得后续对于o的可能存在的操作因异常而终止。

改写如下:

int dividend = 10, divisor = 0;
Optional<Integer> o;
try {    
  int result = dividend / divisor;    
  o = Optional.of(result);
} catch (ArithmeticException e) {  
  o = Optional.empty();
}

访问Optional实例的值
get()

它的源码:

public T get() {    
  if (value == null) {
    throw new NoSuchElementException("No value present");    
  }    
  return value;
}

当Optional实例包装的是一个空值时,它会抛出NoSuchElementException。

所以在调用get()方法前我们还是需要判断Optional是否包装空值。
使用ifPresent()方法来判断其包装的是否是空值:

public static String getGender(Student student) {
  Optional<Student> stuOpt = Optional.ofNullable(student);
   if(stuOpt.isPresent()) {
      return stuOpt.get().getGender();
   }
    
   return "Unkown";
 }

而这其实是一种很糟糕的写法,因为这种用法不但没有减少null的防御性检查,而且增加了Optional包装的过程,违背了Optional设计的初衷,因此开发中要避免这种糟糕的使用。 下文会介绍相对更好的写法。

获取默认值

Optional提供了两种方法来返回默认值。

orElse()

orElse()会在Optional有值时返回它的值,否则就会返回传入的默认值。

public class Main {
  public static void main(String[] args) {
    System.out.println(getGender(null));    
  }    
  
  public static String getGender(Student student) {
    Student stuOpt = Optional.ofNullable(student).orElse(new Student();        
    return stuOpt.getGender();    
  }
}

orElseGet()

orElseGet()则稍有不同,它会在Optional有值时返回其值,否则就会执行作为参数传入的Supplier实例的get()方法,并返回其执行结果。

public class Main {
  public static void main(String[] args) {
    System.out.println(getGender(null));    
  }    
  
  public static String getGender(Student student) {
    Student stuOpt = Optional.ofNullable(student).orElseGet(Student::new);      
    return stuOpt.getGender();    
  }
}

两者的不同之处

  • orElse()是EAGER的,也就是说无论Optional的值是否为空,它都会执行。
  • orElseGet()是LAZY的,只有当Optional的值为空时,才会执行。

由于由以上差异,我们要根据业务场景谨慎选择,尤其是涉及服务调用或数据查询等耗时操作时。

以上就是如何使用Java中的Optional的详细内容,更多关于Java中的Optional的资料请关注脚本之家其它相关文章!

相关文章

  • Java 数据类型及类型转换的互相转换实例代码

    Java 数据类型及类型转换的互相转换实例代码

    这篇文章主要介绍了Java 数据类型及类型转换的互相转换实例代码,需要的朋友可以参考下
    2020-10-10
  • Java操作集合工具类Collections使用详解

    Java操作集合工具类Collections使用详解

    这篇文章主要介绍了java操作集合工具类Collections使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • java中InputStream转为MultipartFile的解决方案

    java中InputStream转为MultipartFile的解决方案

    这篇文章主要介绍了java中InputStream转为MultipartFile的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • IDEA 端口占用的解决方法(推荐)

    IDEA 端口占用的解决方法(推荐)

    这篇文章主要介绍了IDEA 端口占用的解决方法,本文通过两种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Spring Cloud Gateway内置的断言和过滤器作用说明

    Spring Cloud Gateway内置的断言和过滤器作用说明

    这篇文章主要介绍了Spring Cloud Gateway内置的断言和过滤器作用说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • idea项目文件夹横向显示,纵向显示的解决方法

    idea项目文件夹横向显示,纵向显示的解决方法

    这篇文章主要介绍了idea项目文件夹横向显示,纵向显示的解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java 如何优雅的抛出业务异常

    Java 如何优雅的抛出业务异常

    这篇文章主要介绍了Java 如何优雅的抛出业务异常,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-12-12
  • 详解SpringBoot的Run方法

    详解SpringBoot的Run方法

    本文给大家介绍了SpringBoot的Run方法,文中通过实例代码相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-10-10
  • MAC下基于maven使用IDEA走读TestNG源码解析

    MAC下基于maven使用IDEA走读TestNG源码解析

    这篇文章主要介绍了MAC下基于maven使用IDEA走读TestNG源码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-06-06
  • Java中BitMap(位图)hutool版、IntMap、LongMap示例详解

    Java中BitMap(位图)hutool版、IntMap、LongMap示例详解

    这篇文章主要给大家介绍了关于Java中BitMap(位图)hutool版、IntMap、LongMap的相关资料,通过位运算高效存储和检索整数,相比于传统数组,它们在内存占用和性能上都有显著优势,需要的朋友可以参考下
    2024-12-12

最新评论