Guava的Optional课程有什么意义

时间:2012-03-05 03:32:02

标签: java generics guava

我最近读过这篇文章并看过有人使用这个课程,但在几乎所有情况下,使用null也会有效 - 如果不是更直观的话。有人能提供一个具体的例子,Optional能够实现null无法实现的东西,还是更清洁的方式?我唯一能想到的是将它与Maps一起使用,不接受null键,但即便如此,也可以通过null的值的“映射”来完成。任何人都可以给我一个更有说服力的论点吗?谢谢。

4 个答案:

答案 0 :(得分:154)

番石榴团队成员。

null的唯一最大缺点可能是它在任何给定的上下文中应该是什么意思并不明显:它没有说明性的名称。 null表示“此参数没有值”并不总是显而易见的 - 哎,作为返回值,有时它意味着“错误”,甚至是“成功”(!!),或者只是“正确答案”没什么”。 Optional经常是你将变量设为可空时实际意味着的概念,但并非总是如此。如果不是,我们建议您编写自己的类,类似于Optional,但使用不同的命名方案,以明确您的实际含义。

但是我会说Optional的最大优势在于可读性:优点是它的白痴证明。如果您希望程序完全编译,它会强制您主动考虑缺席情况,因为您必须主动解包Optional并解决该情况。 Null使得简单地忘记事情变得非常容易,虽然FindBugs有所帮助,但我认为它几乎不能解决这个问题。当您返回可能存在或可能不存在的值时,这尤其重要。您(以及其他人)更有可能忘记other.method(a, b)可能会返回null值而不是您可能会忘记a可能是null实施other.method。返回Optional使调用者无法忘记这种情况,因为他们必须自己打开对象。

出于这些原因,我们建议您使用Optional作为方法的返回类型,但不一定在方法参数中。

(顺便说一下,这完全是讨论here。)

答案 1 :(得分:9)

它看起来像是来自Haskell的Maybe Monad模式。

您应该阅读以下内容,Wikipedia Monad (functional programming)

阅读From Optional to Monad with Guava上的Kerflyn's Blog,,其中讨论了用作Monad的番石榴的可选项:


修改 对于Java8,内置的Optional具有flatMap等monadic运算符。这是一个有争议的话题,但最终已经实施。

请参阅http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html

public Optional<String> tryFindSimilar(String s)  //...

Optional<Optional<String>> bad = opt.map(this::tryFindSimilar);
Optional<String> similar =       opt.flatMap(this::tryFindSimilar);

flatMap运算符对于允许monadic操作至关重要,并允许轻松链接所有返回Optional结果的调用。

考虑一下,如果您使用map运算符5次,最终会得到Optional<Optional<Optional<Optional<Optional<String>>>>>,而使用flatMap会给您Optional<String>

从Java8开始,我宁愿不使用功能较弱的Guava&#optional。

答案 2 :(得分:6)

使用它的一个很好的理由是它使你的空值非常有意义。而不是返回可能意味着许多事情的空值(如错误,失败或空白等),您可以输入一个名称&#39;你的空。看看这个例子:

让我们定义一个基本的POJO:

class PersonDetails {

String person;
String comments;

public PersonDetails(String person, String comments) {
    this.person = person;
    this.comments = comments;
}

public String getPerson() {
    return person;
}


public String getComments() {
    return comments;
}

}

现在让我们使用这个简单的POJO:

public Optional<PersonDetails> getPersonDetailstWithOptional () {

  PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless,
  lets make the return value more meaningful*/


    if (details == null) {
      //return an absent here, caller can check for absent to signify details are not present
        return Optional.absent();
    } else {
      //else return the details wrapped in a guava 'optional'
        return Optional.of(details);   
    }
}

现在让我们避免使用null并使用Optional执行我们的检查,使其具有意义

public void checkUsingOptional () {

    Optional<PersonDetails> details = getPersonDetailstWithOptional();

    /*below condition checks if persons details are present (notice we dont check if person details are null,
    we use something more meaningful. Guava optional forces this with the implementation)*/
    if (details.isPresent()) {

      PersonDetails details = details.get();

        // proceed with further processing
        logger.info(details);

    } else {
        // do nothing
        logger.info("object was null"); 
    }

    assertFalse(details.isPresent());
}

因此最终它使一种使空值有意义的方法,&amp;不那么含糊。

答案 3 :(得分:4)

Optional最重要的优点是它为函数的实现者和调用者之间的契约添加了更多细节。因此,这对参数和返回类型都很有用。

如果您使约定对于可能的空对象始终具有Optional,则可以对以下情况添加更多说明:

  1. Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)

    此处的合同明确规定,有可能不会返回结果,但也会显示它可以与fromto一起使用。

  2. Optional<Integer> maxPrime(Optional<Integer> from, Integer to)

    合同指定from是可选的,因此缺席值可能具有特殊含义,例如从2开始。我可以预期to参数的空值将抛出异常。

  3. 因此,使用Optional的好处在于合同既具有描述性(类似于@NotNull注释),又具有正式性,因为您必须编写代码.get()来应对Optional。< / p>