【问题标题】:How to check if is null and if has a specific value using Optional in java?java - 如何使用Java中的Optional检查是否为null以及是否具有特定值?
【发布时间】:2017-03-28 00:34:35
【问题描述】:

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

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

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

【问题讨论】:

  • 如果参数是可选的,那么创建两个方法:一个没有参数,一个期望一个int。 ifOptional 都不是很好的选择。
  • 不能同意该评论。考虑三个都是可选的参数。当然,您并不是建议对方法进行 2^3=8 重载,尤其是在每个参数都是整数的情况下(使几个不同的签名无法区分)。当然有时我们可以在其他实体中收集所有参数,但我们将再次需要处理它们是可选的。

标签: java if-statement functional-programming java-8 optional


【解决方案1】:

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,该Optional 包装的元素应应用于该元素。

最后,您可以简单地使用ifPresent() 执行一些操作,抛出异常orElseThrow 或简单地使用orElseorElseGet 返回默认值。请记住,orElseGet 接受 Supplier 实例,这使得它可以懒惰地评估默认值。

如果您想深入了解,请查看 Devoxx 的 @stuart-marks 演讲:https://www.youtube.com/watch?v=Ej0sss6cq14&t=2767s

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

【讨论】:

  • 很抱歉被接受了答案。支持您的回答,并希望您在这里获得民粹主义徽章。
  • “应该是这样的” 我不这么认为。在对另一个答案的评论中,您写道_“作为参数可选是代码味道”,但您的代码基本上就是这样做的。无论您期待Optional 还是创建一个都没有区别。代码气味是可选参数,不是Optional的用法。
  • @zeroflagL 好吧,创建一个 Optional 实例只是为了从 API 中受益是有问题的,但请记住,它是封装的而不是公开的。您不会强迫用户将所有内容包装到 Optional 中。
【解决方案2】:

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

正如Stuart Marks 中的Optional - The Mother of All Bikesheds 所说:

Rule #4:创建 Optional 以实现从其中链接方法以获取值的特定目的通常不是一个好主意。

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

Rule #6:避免在字段、方法参数和集合中使用 Optional。

避免在方法参数中使用 Optional

  • 将参数设为可选并不真正起作用
  • 强制调用站点为所有内容创建 Optional:

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

    myMethod(Optional.empty());

另见Why should Java 8's Optional not be used in arguments

【讨论】:

    【解决方案3】:

    使用Optional&lt;Integer&gt;

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

    Optional&lt;&gt; 只是可选模式的一个实现。有用的方法也是Optional&lt;T&gt;#orElse(T default),它将值设置为默认值,以防null

    如果您已经感兴趣但仍然无法回答您的疑问,请在 cmets 中寻求澄清。我会尽快回复。

    【讨论】:

    • if 条件可以缩短为 parameter.filter((i) -> i > -1).isPresent()
    • @Nevay 并非每个初学者都熟悉 lambda,所以我决定展示 传统 方式。
    • @xenteros OP 不得不使用引用类型,因为他们允许它为 null - 因此转换为可选类型。
    • 您不应将Optional 用作方法的参数。我找到了一个很好的答案来解释原因:stackoverflow.com/a/39005452/4137489
    • 这个答案真的很糟糕。 Optional 作为参数是一种代码味道,建议使用 Optional 的方式与应该如何使用它无关。
    【解决方案4】:

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

    • 您希望它像以前一样继续工作,并处理客户端提供 null 的情况
    • 您想更改方法以接受Optional&lt;Integer&gt; 作为其参数。 “无空值”的方法是这样做,并且根本不容纳提供 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&lt;Integer&gt;

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

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

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

    【讨论】:

      【解决方案5】:
      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
      

      【讨论】:

      • 这只能回答一半的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-25
      • 2012-11-04
      • 2023-02-16
      • 2021-12-02
      • 2018-06-11
      相关资源
      最近更新 更多