还在用 !=null 判空?让我们用Java8的全新API去优化代码吧

在这里插入图片描述

当我们编写Java代码时,经常需要处理空值(null),因为空值可能导致NullPointerException异常,这是一个常见的运行时异常。在Java 8中,引入了Optional类来更优雅地处理可能为空的值,从而减少NullPointerException的发生。在本篇博客中,我们将深入讨论Optional类的使用方法,并通过大量的示例来演示如何使用它来提高代码的可读性和稳健性。

什么是Optional?

Optional是Java 8中的一个新类,用于表示一个值可能存在也可能不存在的情况。它可以看作是一个容器,可以包含一个非空的值,也可以不包含任何值(即空值)。通过使用Optional,我们可以明确地处理这两种情况,而不是依赖于条件判断来检查空值。

创建Optional对象

Optional类中,有几种方式来创建Optional对象:

  1. 使用of(T value):如果我们确定值不会为空,可以使用of方法创建一个非空的Optional对象。如果传递了一个空值,将抛出NullPointerException
Optional<String> nonEmptyOptional = Optional.of("Hello, Optional!");
  1. 使用ofNullable(T value):如果值可能为空,可以使用ofNullable方法创建一个Optional对象。这个方法可以接受空值。
String nullableValue = getNullableValue(); // 可能为空的值
Optional<String> optional = Optional.ofNullable(nullableValue);
  1. 使用empty():创建一个空的Optional对象。
Optional<String> emptyOptional = Optional.empty();

访问Optional中的值

我们可以使用以下方法来访问Optional对象中的值:

  1. get():获取Optional对象中的值。但要小心,如果Optional为空,调用get()方法将抛出NoSuchElementException异常。
Optional<String> optional = Optional.of("Hello, Optional!");
String value = optional.get(); // 获取值
  1. orElse(T other):如果Optional为空,返回指定的默认值。
Optional<String> optional = Optional.empty();
String value = optional.orElse("Default Value"); // 使用默认值
  1. orElseGet(Supplier<? extends T> other):如果Optional为空,可以使用orElseGet方法提供的函数生成默认值。这种方式可以用来延迟计算默认值。
Optional<String> optional = Optional.empty();
String value = optional.orElseGet(() -> generateDefaultValue()); // 使用默认值生成函数
  1. orElseThrow(Supplier<? extends X> exceptionSupplier):如果Optional为空,可以使用orElseThrow方法抛出指定的异常。
Optional<String> optional = Optional.empty();
String value = optional.orElseThrow(() -> new IllegalStateException("Value is empty"));

判断Optional是否包含值

我们可以使用以下方法来判断Optional是否包含值:

  1. isPresent():如果Optional包含值,返回true,否则返回false
Optional<String> optional = Optional.of("Hello, Optional!");
boolean isPresent = optional.isPresent(); // true
  1. ifPresent(Consumer<? super T> consumer):如果Optional包含值,执行指定的操作。
Optional<String> optional = Optional.of("Hello, Optional!");
optional.ifPresent(value -> System.out.println("Value: " + value));

使用Optional的链式操作

当使用Optional的链式操作时,我们可以将一系列操作连接在一起,以更清晰和流畅的方式处理值。这种方法可以有效地避免繁琐的条件检查和嵌套,提高代码的可读性和简洁性。以下是一些示例,详细解释和分析Optional链式操作的用法:

示例 1: 获取用户的姓名

假设我们有一个User对象,但它可能为空。我们想从中获取用户的姓名,如果用户为空或姓名为空,则使用默认值。

User user = getUser(); // 可能为空的User对象

String userName = Optional.ofNullable(user) // 将User包装成Optional
    .map(u -> u.getName()) // 获取用户的姓名
    .orElse("Unknown"); // 如果为空,使用默认值

System.out.println("User Name: " + userName);
  • Optional.ofNullable(user) 将可能为空的user对象包装成Optional

  • map(u -> u.getName())Optional中获取用户的姓名。如果user为空,map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果用户为空或姓名为空,则返回默认值。

示例 2: 处理嵌套的数据

有时,我们可能有一个嵌套的数据结构,如User对象内部包含Address对象。我们想要获取用户的城市信息,但任何层级的数据都可能为空。

User user = getUser(); // 可能为空的User对象

String city = Optional.ofNullable(user) // 将User包装成Optional
    .flatMap(u -> Optional.ofNullable(u.getAddress())) // 获取Address对象,可能为空
    .map(address -> address.getCity()) // 获取城市信息
    .orElse("Unknown"); // 如果为空,使用默认值

System.out.println("City: " + city);
  • Optional.ofNullable(user) 将可能为空的user对象包装成Optional

  • flatMap(u -> Optional.ofNullable(u.getAddress())) 用于获取嵌套的Address对象,这里使用flatMap以平滑处理可能为空的情况。

  • map(address -> address.getCity())Optional中获取城市信息。如果useraddress为空,map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果城市信息为空,则返回默认值。

示例 3: 处理集合中的Optional

有时,我们可能在集合中包含Optional,需要从中提取数据并进行处理。例如,我们有一个包含可能为空的用户的列表,我们想获取他们的姓名,并将姓名连接成一个字符串。

List<Optional<User>> userList = getUserList(); // 包含可能为空的User的列表

String userNames = userList.stream()
    .map(optionalUser -> optionalUser
        .map(User::getName) // 获取用户的姓名,可能为空
        .orElse("Unknown")) // 如果为空,使用默认值
    .collect(Collectors.joining(", ")); // 连接姓名

System.out.println("User Names: " + userNames);
  • map(optionalUser -> ...)中,我们首先使用内部的map操作获取用户的姓名。如果optionalUser为空,则内部的map操作会被跳过,不会导致NullPointerException。

  • orElse("Unknown") 用于指定默认值,如果姓名为空,则返回默认值。

  • 最后,我们使用collect方法将所有的姓名连接成一个字符串,用逗号分隔。

这些示例演示了如何使用Optional的方法链式地处理数据。通过合理利用mapflatMaporElse等方法,我们可以在不担心空值的情况下处理数据,代码更具可读性和健壮性。这有助于简化代码并减少空指针异常的风险。

猜你喜欢

转载自blog.csdn.net/weixin_53742691/article/details/133377461