如何使用 java 中的 Optional 检查是否为 null 以及是否具有特定值?

How to check if is null and if has a specific value using Optional in java?

假设我的项目中有这段代码:

public List<T> getAll(Integer parameter) {
    if(parameter != null && parameter > -1) {
        // do something here
    }
}

我的问题是:如何使用 Optional 而不是使用 if 进行检查,或者是否还有其他我可以使用的东西?

使用Optional<Integer>

public List<T> getAll(Integer paramter) {
    return Optional.ofNullable(parameter)
      .filter(p -> p > -1);
}

Optional<> 只是 Optional 模式的一个实现。有用的方法也是 Optional<T>#orElse(T default),它将值设置为默认值,以防出现 null

如果你已经感兴趣了,但还是不能解答你的疑惑,欢迎在评论中求解答。我会尽快回复。

Optional 的设计灵感来自于函数式编程世界中众所周知的 monad。在这种情况下,它可能看起来像这样:

public List<T> getAll(Integer parameter) {

    return Optional.ofNullable(parameter)
      .filter(p -> p > -1)
      .map(p -> *some modification*) //this line is optional
      .orElseGet(() -> *some default value, probably an empty list*)
}

在这种情况下,条件检查在filter 方法中执行。如果给定的 Predicate 不匹配,则基础 Optional 将为空。

如果要对基础值执行操作,请使用 map 方法,方法是为其提供一个 Function,该 Function 应应用于 Optional 包装的元素。

最后,您可以使用 ifPresent() 简单地执行一些操作,抛出异常 orElseThrow 或者简单地 return 使用 orElse 或 [=20] 的默认值=].请记住,orElseGet 接受一个 Supplier 实例,这使得它延迟评估默认值。

如果您想深入挖掘,请查看来自 Devoxx 的@stuart-marks 谈话:https://www.youtube.com/watch?v=Ej0sss6cq14&t=2767s

在您的情况下,可能根本不需要 Optional。无非两种方法。一个带参数,一个不带参数

你需要清楚你对你的方法的期望。可能性:

  • 您希望它像以前一样继续工作,并处理客户端提供空值的情况
  • 您想更改方法以接受 Optional<Integer> 作为其参数。 "no nulls" 方法就是这样做,并且根本不适应提供 null 的调用者——如果他们得到 NullPointerException,那是他们自己的错,因为他们违反了规则。

您不必使用流或 lambda 来使用 Optional(当然,您可以)。

你可以简单地写:

public List<T> getAll(Optional<Integer> maybeParameter) {
    if(maybeParameter.isPresent() && maybeParameter.get() > -1) {
        // do something here
    }
}

查看 Optional JavaDoc 中的其他方法,看看它还能如何使用。

如果您不想更改方法的签名,可以使用 Optional.ofNullable()Integer 变成 Optional<Integer>:

public List<T> getAll(Integer parameter) {
    Optional<Integer> maybeParameter = Optional.ofNullable(parameter);
    // work with the Optional here as before...
}

但是我质疑在这里这样做的价值。如果您的 API 接受空值,那么使用 Optional "behind the scenes" 处理它不会提供任何优势。

我觉得 Optional 的最佳用途是将其作为 API 的一部分公开。如果一个参数是可选的,将其声明为 Optional 而不是处理 null (或者更好的是,使用方法重载,这样它们根本不必传递任何东西)。如果可能无法设置 return 值,请将 return 类型设置为 Optional,而不是 return 空值。

import java.util.Optional;

public class ExampleNullCheck{

    public static void main(String args[])
    {
        Integer a = null;
        Optional<Integer> checkInt = Optional.ofNullable(a);
        System.out.println(checkInt.isPresent());
    }//main

}//class

在这种情况下你不应该使用 Optional

作为Stuart Marks states in Optional - The Mother of All Bikesheds:

Rule #4: It's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value.

这会产生无用的开销,而不会提高代码的可读性和可维护性。因此,您不应该将参数包装到可选参数中。

Rule #6: Avoid using Optional in fields, method parameters and collections.

Avoid using Optional in method parameters

  • it doesn't really work for making parameters optional
  • forces call sites to create Optionals for everything:

    myMethod(Optional.of("some value"));

    myMethod(Optional.empty());

另见