简体   繁体   English

番石榴的选修课有什么意义

[英]What's the point of Guava's Optional class

I've recently read about this and seen people using this class, but in pretty much all cases, using null would've worked as well - if not more intuitively. 我最近阅读了有关此内容的文章,并看到人们在使用此类,但是在几乎所有情况下,使用null也会奏效-即使不是更直观。 Can someone provide a concrete example where Optional would achieve something that null couldn't or in a much cleaner way? 有人可以提供一个具体的示例吗,其中Optional可以实现null不能或以更简洁的方式实现? The only thing I can think of is to use it with Maps that don't accept null keys, but even that could be done with a side "mapping" of null's value. 我唯一能想到的就是将其与不接受null键的Maps一起使用,但即使这样,也可以通过对空值的边进行“映射”来实现。 Can anyone provide me with a more convincing argument? 谁能为我提供更令人信服的论点? Thank you. 谢谢。

Guava team member here. 番石榴团队成员在这里。

Probably the single biggest disadvantage of null is that it's not obvious what it should mean in any given context: it doesn't have an illustrative name. null最大缺点可能是,在任何给定的上下文中它的含义都不明显:它没有一个说明性的名称。 It's not always obvious that null means "no value for this parameter" -- heck, as a return value, sometimes it means "error", or even "success" (!!), or simply "the correct answer is nothing". 并非总是很明显, null表示“此参数没有值” –哎呀,作为返回值,有时表示“错误”,甚至是“成功”(!!),或者仅仅是“正确的答案是什么”。 Optional is frequently the concept you actually mean when you make a variable nullable, but not always. 当使变量为可空值时, Optional含义通常是您实际上要表达的概念,但并非总是如此。 When it isn't, we recommend that you write your own class, similar to Optional but with a different naming scheme, to make clear what you actually mean. 如果不是,我们建议您编写自己的类(类似于Optional但使用不同的命名方案),以弄清您的实际含义。

But I would say the biggest advantage of Optional isn't in readability: the advantage is its idiot-proof-ness. 但是我会说Optional的最大优点不是可读性:优点是其防白痴。 It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. 如果您要完全编译程序,它会迫使您积极考虑不存在的情况,因为您必须主动展开Optional并解决该情况。 Null makes it disturbingly easy to simply forget things, and though FindBugs helps, I don't think it addresses the issue nearly as well. Null使得简单地忘记事情变得异常容易,尽管FindBugs有所帮助,但我认为它几乎不能解决这个问题。 This is especially relevant when you're returning values that may or may not be "present." 当您返回可能存在或不存在的值时,这一点尤其重要。 You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method . 你(及其他)更可能忘记other.method(a, b)可以返回一个null比你可能会忘记,值a可能是null当你实现other.method Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves. 返回Optional使调用者无法忘记这种情况,因为调用者必须自己打开对象。

For these reasons, we recommend that you use Optional as a return type for your methods, but not necessarily in your method arguments. 由于这些原因,我们建议您将Optional用作方法的返回类型,但不一定要在方法参数中使用。

(This is totally cribbed, by the way, from the discussion here .) (顺便说一下,这完全是从这里的讨论中得出的。)

It really looks like the Maybe Monad pattern from Haskell. 它看起来真的很像Haskell的Maybe Monad模式。

You should read the following, Wikipedia Monad (functional programming) : 您应该阅读以下内容,Wikipedia Monad(函数式编程)

And read From Optional to Monad with Guava on Kerflyn's Blog, which discusses about the Optional of Guava used as a Monad: 并在Kerflyn的博客上阅读从Optional到 Guad的 Monad 其中讨论了用作Monad的Guava的Optional:


Edit: With Java8, there's a built-in Optional that has monadic operators like flatMap . 编辑:使用Java8,有一个内置的Optional,它具有诸如flatMap单子运算符。 This has been a controversial subject but finally has been implemented. 这一直是一个有争议的主题,但最终得以实现。

See http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html 参见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);

The flatMap operator is essential to allow monadic operations, and permits to easily chain calls that all return Optional results. flatMap运算符对于允许flatMap操作是必不可少的,并且允许轻松地将所有返回可选结果的调用链接在一起。

Think about it, if you used the map operator 5 times you would end up with an Optional<Optional<Optional<Optional<Optional<String>>>>> , while using flatMap would give you Optional<String> 想想看,如果您使用了5次map运算符,您将得到Optional<Optional<Optional<Optional<Optional<String>>>>> ,而使用flatMap会给您Optional<String>

Since Java8 I would rather not use Guava's Optional which is less powerful. 从Java8开始,我宁愿不使用功能不那么强大的Guava的Optional。

One good reason to use it is that it makes your nulls very meaningful. 使用它的一个很好的理由是,它使您的null非常有意义。 Instead of returning a null that could mean many things (like error, or failure, or empty,etc) you can put a 'name' to your null. 可以返回一个“名称”作为替代,而不是返回可能意味着很多事情的空值(例如错误,失败或空值等)。 Look at this example: 看这个例子:

lets define a basic POJO: 让我们定义一个基本的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;
}

} }

Now lets make use of this simple POJO: 现在让我们使用这个简单的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);   
    }
}

Now lets avoid using null and do our checks with Optional so its meaningful 现在让我们避免使用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());
}

thus in the end its a way to make nulls meaningful, & less ambiguity. 因此,最终它是一种使null有意义并减少歧义的方法。

The most important advantage of Optional is that it adds more details to the contract between the implementer and caller of a function. Optional的最重要的优点是它为函数的实现者和调用者之间的协定增加了更多细节。 For this reason is both useful for parameters and return type. 因此,对于参数和返回类型均有用。

If you make the convention to always have Optional for possible null objects you add more clarifications to cases like: 如果使约定对于可能的空对象始终具有Optional对以下情况添加更多说明:

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

    The contract here clearly specifies that there is a chance that a result is not returned but also shows that it will work with from and to as absent. 此处的合同明确规定,有可能不返回结果,但也表明它将与fromto一起使用。

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

    The contract specifies that the from is optional so an absent value might have a special meaning like start from 2. I can expect that a null value for the to parameter will throw an exception. 合同规定from是可选的,因此缺少的值可能具有特殊的含义,例如从2开始。我可以期望to参数的null值将引发异常。

So the good part of using Optional is that the contract became both descriptive (similar with @NotNull annotation) but also formal since you must write code .get() to cope with Optional . 因此,使用Optional的好处在于,合同既具有描述性(类似于@NotNull批注),又具有正式性,因为您必须编写代码.get()来应对Optional

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM