Bri*_*etz 470
当然,人们会做他们想做的事.但是在添加此功能时我们确实有明确的意图,并且它不是通用的类型,就像许多人希望我们这样做一样.我们的目的是为库方法返回类型提供一种有限的机制,其中需要一种明确的方式来表示"无结果",并且使用null
这种方法绝对可能导致错误.
例如,您可能永远不应该将它用于返回结果数组或结果列表的内容; 而是返回一个空数组或列表.您几乎不应该将它用作某事物或方法参数的字段.
我认为通常使用它作为吸气剂的返回值肯定会过度使用.
可选的应该避免使用它没有任何问题,它不是许多人所希望的那样,因此我们非常关注热情过度使用的风险.
(公共服务公告:永远不要打电话,Optional.get
除非你能证明它永远不会是空的;而是使用其中一种安全方法,如orElse
或ifPresent
.回想起来,我们应该调用get
类似的getOrElseThrowNoSuchElementException
东西,或者更清楚地说这是一种非常危险的方法从一开始就破坏了整个目的Optional
.经验教训.(更新:Java 10具有Optional.orElseThrow()
,在语义上等同于get()
,但其名称更合适.))
Jus*_*tin 69
在对我自己进行了一些研究之后,我发现了一些可能暗示适当的事情.最具权威性的是来自Oracle文章的以下引用:
"重要的是要注意Optional类的意图不是替换每个单独的null引用.相反,它的目的是帮助设计更易于理解的API,这样只需读取方法的签名,就可以判断出是否存在可以期待一个可选值.这会强制你主动打开一个Optional来处理缺少值." - 厌倦了空指针异常?考虑使用Java SE 8的可选项!
"可选并不意味着在这些情况下使用,因为它不会给我们任何东西:
- 在域模型层(不可序列化)
- 在DTO中(同样的原因)
- 在输入参数的方法
- 在构造函数参数中"
这也似乎提出了一些有效的观点.
我无法发现任何负面含义或危险信号表明Optional
应该避免.我认为一般的想法是,如果它有用或者提高了API的可用性,请使用它.
Cla*_*lke 19
我会说一般来说,将可选类型用于可以为空的返回值是一个好主意.然而,对于框架我认为用可选类型替换经典getter在使用依赖于getter和setter的编码约定的框架(例如,Hibernate)时会带来很多麻烦.
Optional
添加到Java 的原因是因为:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
Run Code Online (Sandbox Code Playgroud)
比这更清洁:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
Run Code Online (Sandbox Code Playgroud)
我的观点是,Optional是为支持函数式编程而编写的,它同时被添加到Java中.(这个例子来自Brian Goetz的一篇博客.一个更好的例子可能会使用这个orElse()
方法,因为这个代码无论如何都会抛出异常,但是你得到了这个.)
但现在,人们使用Optional是出于一个非常不同的原因.他们用它来解决语言设计中的缺陷.缺点是:没有办法指定API的参数和返回值中的哪一个允许为空.它可能在javadocs中提到过,但是大多数开发人员甚至都没有为他们的代码编写javadoc,并且没有多少人会在编写时检查javadoc.因此,这会导致许多代码在使用它们之前始终检查空值,即使它们通常不能为空,因为它们已经在调用堆栈上重复验证了九次或十次.
我认为解决这个漏洞真的很渴望,因为很多人看到新的Optional类的目的是为了增加API的清晰度.这就是为什么人们会问"应该让getters返回Optionals?"这样的问题.不,它们可能不应该,除非您希望将getter用于函数式编程,这是不太可能的.实际上,如果你看一下Java API中使用Optional的地方,它主要是在Stream类中,它们是函数式编程的核心.(我没有仔细检查过,但Stream类可能是他们使用的唯一地方.)
如果您计划在一些功能代码中使用getter,那么最好使用标准的getter和第二个返回Optional的getter.
哦,如果你需要你的类可序列化,你绝对不应该使用Optional.
可选项是API缺陷的一个非常糟糕的解决方案,因为a)它们非常冗长,并且b)它们从来没有打算首先解决这个问题.
Nullness Checker是一个更好的API缺陷解决方案.这是一个注释处理器,允许您通过使用@Nullable注释它们来指定允许哪些参数和返回值为null.这样,编译器可以扫描代码并确定是否将实际为null的值传递给不允许null的值.默认情况下,它假定除非对其进行注释,否则不允许任何内容为空.这样,您不必担心空值.将null值传递给参数将导致编译器错误.测试null为null的对象会产生编译器警告.这样做的结果是将NullPointerException从运行时错误更改为编译时错误.
这改变了一切.
至于你的getter,不要使用Optional.并尝试设计您的类,因此没有成员可能为null.并且可以尝试将Nullness Checker添加到您的项目中,并在需要时声明您的getter和setter参数@Nullable.我只用新项目完成了这项工作.它可能会在现有的项目中产生很多警告,这些项目都是用null进行大量多余的测试,所以改造可能很难.但它也会遇到很多错误.我喜欢它.因为它,我的代码更清晰,更可靠.
(还有一种新的语言可以解决这个问题.编译为Java字节代码的Kotlin允许您在声明对象时指定对象是否为空.这是一种更清晰的方法.)
原帖(第2版)附录
经过深思熟虑之后,我不情愿地得出结论:在一个条件下返回Optional是可以接受的:检索到的值实际上可能为null.我看过很多代码,人们经常从getter返回Optional,这些getter不可能返回null.我认为这是一种非常糟糕的编码实践,只会增加代码的复杂性,从而使错误更容易发生.但是当返回的值实际上可能为null时,请继续将其包装在Optional中.
请记住,为函数式编程而设计的方法以及需要函数引用的方法将(并且应该)以两种形式编写,其中一种使用Optional.例如,Optional.map()
并且Optional.flatMap()
都接受函数引用.第一个引用普通的getter,第二个引用一个返回Optional的引用.因此,如果值不能为null,则返回可选项,而不是帮助任何人.
说了这么多,我仍然看到Nullness Checker使用的方法是处理空值的最佳方法,因为它们将NullPointerExceptions从运行时错误转换为编译时错误.
归档时间: |
|
查看次数: |
51031 次 |
最近记录: |