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(...));
比这更干净:
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;
我的观点是,Optional是为了支持函数式编程而编写的,该函数是同时添加到Java中的。(该示例由Brian Goetz的博客提供。一个更好的示例可能使用该orElse()
方法,因为无论如何此代码都会引发异常,但您可以理解。)
但是现在,人们使用Optional的原因非常不同。他们正在使用它来解决语言设计中的缺陷。缺陷在于:无法指定API的哪个参数和返回值允许为空。它可能会在javadocs中提到,但是大多数开发人员甚至都没有为他们的代码编写javadocs,并且没有多少人会在编写时检查javadocs。因此,这导致很多代码在使用空值之前总是检查空值,即使它们经常不可能为空值也是如此,因为它们已经在调用堆栈中重复验证了九到十次。
我认为真正需要解决此缺陷,因为看到新Optional类的许多人都认为它的目的是增加API的清晰度。这就是为什么人们会问诸如“吸气剂应返回可选件”之类的问题吗?不,他们可能不应该这样做,除非您希望将getter用于函数式编程中,否则这种可能性很小。实际上,如果您查看Optional在Java API中的使用位置,那么它主要在Stream类中,Stream类是函数式编程的核心。(我还没有进行非常彻底的检查,但是Stream类可能是唯一使用它们的地方。)
如果确实打算在一些功能代码中使用吸气剂,那么最好使用标准的吸气剂,而第二个吸气剂则返回Optional。
哦,如果您需要类可序列化,则绝对不要使用Optional。
可选参数是解决API缺陷的非常糟糕的解决方案,因为a)它们非常冗长,并且b)从来没有打算首先解决该问题。
Nullness Checker是API缺陷的更好解决方案。这是一个注释处理器,通过使用@Nullable对其进行注释,您可以指定允许哪些参数和返回值为空。这样,编译器可以扫描代码并确定是否将实际上可以为null的值传递给不允许为null的值。默认情况下,它假定没有任何内容可以为null,除非有注释。这样,您不必担心空值。将空值传递给参数将导致编译器错误。测试对象的null不能为null会产生编译器警告。这样做的结果是将NullPointerException从运行时错误更改为编译时错误。
这改变了一切。
至于您的吸气剂,请不要使用Optional。并尝试设计您的类,以便所有成员都不能为空。也许尝试将Nullness Checker添加到项目中,并在需要时声明@Nullable的getter和setter参数。我只在新项目中做到了这一点。它可能会在现有项目中产生很多警告,这些警告中包含许多多余的null测试,因此可能很难进行改进。但这也会捕获很多错误。我喜欢它。因此,我的代码更加简洁,可靠。
(还有一种新的语言可以解决这个问题。Kotlin可以编译为Java字节码,它允许您指定在声明对象时是否可以为null。这是一种更干净的方法。)
原始帖子的附录(版本2)
经过深思熟虑,我很不情愿地得出一个结论,在一个条件下返回Optional是可以接受的:检索到的值实际上可能为null。我看过很多代码,人们通常从无法正常返回null的getter中返回Optional。我认为这是一种非常糟糕的编码实践,只会增加代码的复杂性,从而更容易出现错误。但是,当返回的值实际上可能为null时,请继续将其包装在Optional中。
请记住,为函数式编程设计的方法和需要函数引用的方法将(并且应该)以两种形式编写,其中一种使用Optional。例如,Optional.map()
和Optional.flatMap()
都采用函数引用。第一个引用一个普通的getter,第二个引用一个返回Optional的引用。因此,如果返回值不能为null的Optional,则不会帮任何忙。
综上所述,我仍然看到Nullness Checker所使用的方法是处理null的最佳方法,因为它们将NullPointerExceptions从运行时错误转换为编译时错误。