Java - 用期权处理空值

129 阅读6分钟

在这篇文章中,我们将介绍Java的一个基本主题,即空值处理,我们将使用Java 8中引入的Optionals来实现这一目标,我们将通过实例来详细介绍这一做法。

我们将创建返回Optional的方法,也将看到Spring使用Optional进行数据库操作的方式。首先,让我们记住什么是NullPointerException,然后看一下什么是Optionals。

在Java中,如果我们想创建一个变量,我们首先声明它,然后初始化它。当我们使用一个在内存中没有任何位置的引用(未初始化)并对其进行操作(例如调用方法)时,我们会得到NullPointerException。你可以看到下面的一个例子。

Object someObject = null; // created null variable

在这里,我们有一个名为someObject的未初始化的对象,并试图对其调用toString方法。由于它没有被初始化,并且在内存中没有任何地方被引用,所以它最终会抛出NullPointerException。现在,如果我们刷新了我们的记忆,我们就可以看到Optionals了。

1- 什么是可选类?

可选类提供了一种方法,可以通过流畅的API以优雅的方式处理可忽略的对象。通过提供的API,如果对象存在(非空),我们将对该对象进行处理。让我们看看它是什么样子的

Object someObject = null;

正如你在上面看到的,我们将someObject变量设置为null,然后创建了Optional对象来包裹null对象。然后,我们用isPresent方法检查了该变量是否为空。让我们试试非空对象,看看它是否打印为真,因为我们将非空对象传递给Optional包装器。

Object someObject2 = new Object();

2- 可选类的方法

现在,让我们看看我们可以用什么方法来充分利用Optional类。

我们可以从创建方法开始。这些创建方法是Optional类中的静态方法。

  • ofNullable(T value), 创建Optional类,包裹一个可以是空的或非空的对象。
Optional<Object> optional = Optional.
  • of(T value), 创建Optional包覆一个不能为空的对象。
Optional<Object> optional = Optional.

你可能会问 "如果我们确保传递的对象不是空的,我为什么要使用它"。在某些情况下,你需要在你的方法中返回Optional对象,这是实现一个接口的方法的结果,所以你可能需要这个方法。

  • empty(), 创建空的Optional,这意味着Optional对象中不存在任何值。
Optional<Object> optional = Optional.

现在,让我们看一下检查值是否存在的方法。

  • isPresent(),如果Optional包含非空值,则返回true,否则返回false。
Optional<Object> optional = Optional.
  • ifPresent(Consumer<?super T> consumer),让你在Optional中的值存在的情况下运行你自己的逻辑。
Optional<String> stringOptional = Optional.

你可以在传统的if语句中使用isPresent,或者你可以选择ifPresent以一种优雅的方式来处理现有的值。

我们有时需要在值不存在的情况下运行一些逻辑,比如提供备份值。让我们看看我们如何处理不存在的值。

  • orElse(T other), 如果存在,返回Optional里面的值,否则返回给定的值作为参数。
Optional<String> stringOptionalNull = Optional.

正如你所看到的,stringOptionalNull是一个空的Optional,我们提供了一个备份值,以防它不存在,多亏了orElse方法。所以,它打印了给orElse方法的值。

  • **orElseGet(Supplier<? extends T> other),**如果存在的话,返回Optional里面的值,否则运行提供的逻辑,然后返回其结果。
Optional<String> stringOptionalNull = Optional.

如果我们在一系列操作后提供一个备份值,我们可以利用orElseGet方法。

以下是重要说明

在谈论另一个方法之前,我们将看到orElse和orElseGet方法的一个重要区别。当你为orElse方法提供一个函数时,无论该值是否存在于Optional中,它都会运行给定的方法。对于orElseGet方法,如果该值存在于Optional中,它将不会运行给定的方法。让我们通过一个例子来看看这个问题。

public static void main(String[] args) {
}
public static String getStr() {
// Above program prints only one "I am being evaluated"

我们首先创建了一个值为 "I exist... "的可选字符串。然后,我们通过给getStr()方法作为参数来应用orElse方法。正如我们之前所说,即使值是存在的,orElse也会评估给它的方法。所以,它将打印 "我正在被评估"。然后,我们有orElseGet方法,它有给定的lambda表达式。这一次,它不打算运行给定的lambda,因为值是存在的。如果值不存在,例如最初是Optional.empty(),它将打印两个 "我正在被评估"。让我们继续讨论我们将讨论的最后一个函数。

  • **orElseThrow(Supplier<? extends X> exceptionSupplier),**在值不存在的情况下抛出提供的异常。
Optional<String> stringOptionalNull = Optional.
// Result

我们可以看到orElseThrow抛出了异常,因为Optional里面的值不存在。

最后,让我们看看最基本的方法,我们可以用它来获取Optional对象中的值。

  • get(),简单地返回Optional对象中的值。

我们需要谨慎使用get函数,首先要检查是否存在。如果Optional对象中不存在任何值,那么这个方法将抛出NoSuchElementException。所以,我们可以按照下面的方法使用它,或者直接使用ifPresent方法。

if (someConditional.isPresent()) {

例子

由于我们涵盖了Optional方法,我们可以看一下核心Java和Spring应用程序中的一些例子。

想象一下,我们有一个作为缓存的类,我们可以获得键值为String类型的对象。在这种情况下,使用Optionals不是很有意义吗,因为我们可能没有一个与给定键相关的对象。让我们来看看它的作用

public enum  ObjectCache {

在ObjectCache类中,我们有三个与objectMap交互的方法。当我们使用get方法的时候,它不一定有相关的对象,如果我们对返回的空对象进行操作,我们会面临NullPointerException。但是在上面的类中,我们返回Optional,客户可以将其与我们之前谈到的方法一起使用,以确保null安全。

另一个用例是在Spring应用程序中。在数据层中,我们做一些查询,并从数据库中返回值。在上述相同的逻辑下,它可能没有相应的值,所以它可能会返回空值。在这种情况下,最好是用Optionals包装的返回值。让我们来看看。

@Repository

这里,我们有两个方法。例如,对于findByUsername方法,我们传递用户名,它从数据库中返回相关用户。但是,这样的用户可能不存在。在这种情况下,我们最好将User包在Optional里面,以便更好地处理空值。

在这篇文章中,我谈到了在Java中用Optionals处理空值。我希望你喜欢它。更多类似的文章,你可以关注我。