RAY*_*RAY 87 java generics guava
我最近读过这篇文章并看过有人使用这个课程,但在几乎所有情况下,使用它null都会起作用 - 如果不是更直观的话.有人能提供一个具体的例子Optional来实现null无法或更清洁的方式吗?我唯一能想到的就是使用Maps不接受null密钥的东西,但即便如此,也可以使用null值的"映射"来完成.任何人都可以给我一个更有说服力的论点吗?谢谢.
Lou*_*man 153
番石榴团队成员在这里.
可能最大的缺点null是,在任何给定的环境中,它的含义并不明显:它没有说明性的名称.这并不总是显而易见的null意思是"这个参数没有价值" - 作为一个返回值,有时它意味着"错误",甚至"成功"(!!),或者只是"正确的答案是什么".Optional当你将变量变为可空时,这通常是你实际意味着的概念,但并非总是如此.如果不是,我们建议您编写自己的类,类似Optional但使用不同的命名方案,以明确您的实际含义.
但我认为最大的优势Optional在于可读性:优点是它的白痴证明.如果你想让你的程序完全编译,它会强迫你积极思考缺席的情况,因为你必须主动打开Optional并解决这种情况.Null使得简单地忘记事情变得非常容易,虽然FindBugs有所帮助,但我认为它几乎不能解决这个问题.当您返回可能存在或可能不存在的值时,这尤其重要.你(及其他)更可能忘记,other.method(a, b)可以返回一个null比你可能会忘记,值a可能是null当你实现other.method.返回Optional使得呼叫者无法忘记这种情况,因为他们必须自己解开对象.
出于这些原因,我们建议您Optional将方法用作方法的返回类型,但不一定在方法参数中.
(顺便说一句,从这里的讨论来看,这完全是残缺的.)
它看起来真的像MaybeHaskell 的Monad模式.
您应该阅读以下内容,Wikipedia Monad(函数式编程):
在Kerflyn的博客上阅读From Optional to Monad with Guava , 其中讨论了用作Monad的Guava的可选性:
编辑:
使用Java8,有一个内置的Optional,它有monadic运算符flatMap.这是一个有争议的话题,但最终已经实施.
见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);
Run Code Online (Sandbox Code Playgroud)
该flatMap运营商是必不可少的,让一元操作,并允许轻松调用链所有返回可选结果.
想一想,如果你使用了map5次操作员,你会得到一个Optional<Optional<Optional<Optional<Optional<String>>>>>,而使用flatMap会给你Optional<String>
从Java8开始,我宁愿不使用功能较弱的Guava的Optional.
使用它的一个很好的理由是它使你的空值非常有意义.您可以在null中添加"名称",而不是返回可能意味着很多事情的空(例如错误,失败或空等).看看这个例子:
让我们定义一个基本的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;
}
Run Code Online (Sandbox Code Playgroud)
}
现在让我们使用这个简单的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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在让我们避免使用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());
}
Run Code Online (Sandbox Code Playgroud)
因此最终它是一种使空值有意义且不那么模糊的方法.
Optional 最重要的优点是它为函数的实现者和调用者之间的契约添加了更多细节。因此对于参数和返回类型都很有用。
如果您约定始终对Optional可能的空对象进行约定,则可以对以下情况添加更多说明:
Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)
这里的合同明确规定,有可能不返回结果,但也表明它将与from缺席to一起工作。
Optional<Integer> maxPrime(Optional<Integer> from, Integer to)
合同指定 from 是可选的,因此缺少的值可能具有特殊含义,例如从 2 开始。我可以预期参数的 null 值to将引发异常。
因此,使用Optional的好处是,契约既具有描述性(类似于@NotNull注释),又具有正式性,因为您必须编写代码.get()来处理Optional.