关于后端:使用Optional优雅避免空指针异常

6次阅读

共计 4745 个字符,预计需要花费 12 分钟才能阅读完成。

本文已收录至 Github,举荐浏览 👉 Java 随想录
微信公众号:Java 随想录

摘要

空指针异样(NullPointerException)能够说是 Java 程序员最容易遇到的问题了,影响说大不大,说小也不小。为了解决这个问题,Java 8 版本中推出了 Optional 类。Optional 类是一个容器对象,它能够蕴含或不蕴含非空值。应用 Optional 类能够无效地防止空指针异样的问题。在本篇博客中,我将向大家介绍 JDK Optional 类及其应用办法。

Optional 介绍

Optional 类是一个容器对象,它能够蕴含或不蕴含非空值。如果一个对象可能为空,那么咱们就能够应用 Optional 类来代替该对象。Optional 类型的变量能够有两种状态:存在值和不存在值 Optional 类有两个重要的办法:of 和 ofNullable。of 办法用于创立一个非空的 Optional 对象,如果传入的参数为 null,则会抛出NullPointerException 异样。而 ofNullable 办法用于创立一个能够为空的 Optional 对象。如果传入的参数为空,则返回一个空的 Optional 对象。当 Optional 对象存在值时,调用 get() 办法能够返回该值;当 Optional 对象不存在值时,调用 get() 办法会抛出 NoSuchElementException 异样。

上面是一个应用 Optional 类的例子:

Optional<String> optional = Optional.of("Hello World");
System.out.println(optional.get()); // 输入 Hello World

在下面的例子中,咱们首先应用 of() 办法创立了一个蕴含字符串 “Hello World” 的 Optional 对象,而后应用 get() 办法获取该对象的值并将其打印进去。

留神,如果咱们尝试创立一个 null 值的 Optional 对象,则会抛出 NullPointerException 异样。而且,在应用 Optional 类时,咱们应该尽量避免应用 isPresent() 和 get() 办法,因为这些办法可能会引起空指针异样。比拟举荐应用 Optional.ofNullable 来创立 Optional 对象。

Optional 应用

创立 Optional 对象

咱们能够应用以下几种形式来创立 Optional 对象:

  1. Optional.of(value):创立一个蕴含非空值的 Optional 对象。
  2. Optional.empty():创立一个不蕴含任何值的空 Optional 对象。
  3. Optional.ofNullable(value):创立一个可能蕴含 null 值的 Optional 对象。如果 value 不为 null,则该办法会创立一个蕴含该值的 Optional 对象;否则,创立一个空 Optional 对象。

上面是一个应用 Optional.ofNullable() 办法的例子:

String str = null;
Optional<String> optional = Optional.ofNullable(str);
System.out.println(optional.isPresent()); // 输入 false

在下面的例子中,咱们首先申明了一个空字符串 str,并将其赋值为 null。而后,咱们应用 ofNullable() 办法创立了一个 Optional 对象。因为 str 是 null,因而创立的 Optional 对象也是空的。最初,咱们应用 isPresent() 办法查看 Optional 对象是否蕴含值。

orElse()与 orElseGet()

orElse()办法接管一个参数,即为默认值。如果 Optional 对象中的值不为空,则返回该值,否则返回传入的默认值。具体用法如下:

Optional<String> optional = Optional.ofNullable(null);
String result = optional.orElse("default");
System.out.println(result); // 输入 "default"

orElseGet()办法与 orElse()办法相似,也是用于获取默认值的办法。然而,orElseGet()办法接管的参数是一个 Supplier 函数式接口,用于在须要返回默认值时生成该值。具体用法如下:

Optional<String> optional = Optional.ofNullable(null);
String result = optional.orElseGet(() -> "default");
System.out.println(result); // 输入 "default"
orElse() 和 orElseGet()的区别

orElse() 和 orElseGet()特地类似,有必要抽离进去讲下他们之间的区别。

orElse() 办法无论 Optional 对象是否为空都会执行,因而它总是会创立一个新的对象。orElseGet() 办法只有在 Optional 对象为空时才会执行,因而它能够用来提早创立新的对象。

用一个例子感受一下:

    @Test
    void test() {System.out.println("-------- 不为 null 的状况 ----------");
        // 不为 null
        String str1 = "hello";
        String result11 = Optional.ofNullable(str1).orElse(get(str1 + ":orElse()办法被执行了"));
        String result12 = Optional.ofNullable(str1).orElseGet(() -> get(str1 + ":orElseGet()办法被执行了"));
        System.out.println(result11);
        System.out.println(result12);
        System.out.println("-------- 为 null 的状况 ----------");
        // 为 null
        String str2 = null;
        String result21 = Optional.ofNullable(str2).orElse(get(str1 + ":orElse()办法被执行了"));
        String result22 = Optional.ofNullable(str2).orElseGet(() -> get(str2 + ":orElseGet()办法被执行了"));
        System.out.println(result21);
        System.out.println(result22);
    }


    public String get(String name) {System.out.println(name);
        return name;
    }

输入后果如下:

-------- 不为 null 的状况 ----------
hello:orElse()办法被执行了
hello
hello
-------- 为 null 的状况 ----------
hello:orElse()办法被执行了
null:orElseGet()办法被执行了
hello:orElse()办法被执行了
null:orElseGet()办法被执行了

因而,一般来说,如果你心愿在 Optional 对象为空时才创立新的对象,能够应用 orElseGet() 办法。否则,如果你心愿总是创立新的对象,无论 Optional 对象是否为空,能够应用 orElse() 办法,通常来说 orElseGet()更佳,集体也是举荐应用 orElseGet()。

map()与 flatMap()

map() 办法承受一个函数作为参数,该函数将被利用于 Optional 对象中的值。如果 Optional 对象存在值,则将该值传递给函数进行转换,否则返回一个空 Optional 对象

上面是一个应用 map() 办法的例子:

String str = "Hello";
Optional<String> optional = Optional.of(str);
Optional<String> upperCaseOptional = optional.map(String::toUpperCase);
System.out.println(upperCaseOptional.get()); // 输入 HELLO

在下面的例子中,咱们首先应用 of() 办法创立了一个蕴含字符串 “Hello” 的 Optional 对象。而后,咱们应用 map() 办法将该字符串转换为大写模式,并将后果存储到另一个 Optional 对象 upperCaseOptional 中。最初,咱们应用 get() 办法获取 upperCaseOptional 对象中的值并打印进去。

flatMap() 办法与 map() 办法相似,都承受一个函数作为参数。然而,flatMap() 办法返回的是一个 Optional 类型的值。如果函数返回的是一个 Optional 对象,则该办法会将其“开展”,否则返回一个空 Optional 对象。

上面是一个应用 flatMap() 办法的例子:

String str = "hello world";
Optional<String> optional = Optional.of(str);
Optional<Character> result = optional.flatMap(s -> {if (s.length() > 0)
        return Optional.of(s.charAt(0));
    else
        return Optional.empty();});
System.out.println(result.get()); // 输入 h

在下面的例子中,咱们首先创立了一个蕴含字符串 “hello world” 的 Optional 对象。而后,咱们应用 flatMap() 办法将该字符串转换为第一个字符,并将后果存储到另一个 Optional 对象 result 中。最初,咱们应用 get() 办法获取 result 对象中的值并打印进去。

filter()

filter() 办法承受一个谓词(Predicate)作为参数,返回一个 Optional 类型的值。如果 Optional 对象存在值且满足谓词的条件,则返回该 Optional 对象;否则返回一个空 Optional 对象。

上面是一个应用 filter() 办法的例子:

Integer number = 10;
Optional<Integer> optional = Optional.of(number);
Optional<Integer> result = optional.filter(n -> n % 2 == 0);
System.out.println(result.isPresent()); // 输入 true

在下面的例子中,咱们首先创立了一个蕴含整数 10 的 Optional 对象。而后,咱们应用 filter() 办法过滤出该数字是否为偶数,并将后果存储到另一个 Optional 对象 result 中。最初,咱们应用 isPresent() 办法查看 result 对象是否存在值。

总结

Optional 类是 Java 8 引入的一个十分有用的个性,通过应用 Optional 类,咱们能够更加简洁、平安和易读地编写 Java 代码,防止空指针异样等问题。因而,在编写 Java 代码时,咱们应该尽可能地应用 Optional 类来解决可能造成空指针的变量。

然而,Optional 类并不是万能的,它也有一些不足之处。它可能会减少代码的复杂性和执行工夫,因为它须要咱们在应用值之前查看是否存在值。因而在应用 Optional 类时须要审慎权衡利弊。


本篇文章就到这里,感激浏览,如果本篇博客有任何谬误和倡议,欢送给我留言斧正。文章继续更新,能够关注公众号第一工夫浏览。

正文完
 0