我应该在每个可能返回null的方法中使用Java8/Guava Optional吗?
Java 8引入的Optional类是为了解决空指针异常的问题。然而,与Guava相比,Java 8的Optional存在一个令人讨厌的问题,就是它没有提供一个像orElse(Optional<T>): Optional<T>
这样的方法,而Guava的Optional则定义了这个方法。这个缺少的特性限制了Java 8的Optional在Monad应用方面的使用。
然而,在Java 8中,我们可以通过以下方式模拟Guava的or(Optional<T>)
方法:
optionalA.map(Optional::of).orElse(optionalB)
或者
optionalA.map(Optional::of).orElseGet(() -> computeOptionalB)
另外,在Java 9中,我们终于可以使用Optional.or(Supplier<Optional<T>>)
方法了:
optionalA.or(() -> computeOptionalB)
这真是太棒了!
另外,opt.flatMap(fn)
等价于opt.isPresent()?fn.apply(opt.value):opt
,而opt.orElse(opt2)
等价于opt.isPresent()?opt:opt2
。你能发现它们之间的区别吗?
在java.util.Optional
中有T orElse(T other)
方法,而orElse(T)
返回T,而orElse(Optional<T>)
返回Optional<T>。你能看出两者之间的区别吗?
Java团队非常贴心地意识到Guava的Optional非常有用,并将其添加到Java 8中,同时确保这两个库在细微之处是不兼容的。
(本文参考了stackoverflow.com上的讨论内容)
应该为每个可能返回null的方法使用Java8 / Guava Optional吗?
问题的出现原因:
- Java中存在null引用的概念,无法完全摆脱存在的null引用。
- Optional对象并不能完全取代null引用,它只是另一个引用,会受到与语言中其他引用相同的弱点的影响。
- Optional在Java中的使用价值以及它们是否有价值一直是一个争论的焦点。
- 一些反对者认为,存在其他替代方案(例如,IDE如IntelliJ和Eclipse IDE支持一组专有注释用于对nullability进行静态分析)。
- 一些人希望它能够像函数式世界中那样使用,但在Java中不完全可能,因为Java缺乏函数式编程语言(例如SML或Haskell)中存在的许多功能(例如模式匹配)。
- 一些人认为,不可能将现有代码改为使用Optional的习惯用法。
- 缺乏对可选值的语言支持可能会导致Optional在API中使用不一致,从而创建不兼容性,类似于无法改用新的Optional类的其余Java API。这与Java SE 8的新Optional类不兼容的情况非常相似。
- Optional的好处确实值得商榷,并且可能仅限于提高可读性和强制执行公共接口约定。
解决方法:
- Optional的采用可能使我们的代码更安全,更不容易出现null引用问题,从而更健壮,更少出错。
- 程序员应遵循不在期望可选对象的地方传递null引用的约定。
- Optional的使用需要API设计人员自行决定。
根据Google Guava的文章,Optional的最大优点是其简单易用性,它迫使我们在编写程序时积极思考缺失的情况。
对于Java的Optional API,一些开发人员建议不要使用"get"方法,而应该始终使用"orElse"或"orElseGet"方法来解包Optional并返回一个值,并且最好是非null值。如果不想解包值,可以使用"isPresent"方法进行检查。
Optional的使用有一定的争议,但它可能会提高代码的可读性,并强制执行公共接口约定。然而,Optional并不能完全取代null引用,程序员应遵循不在期望可选对象的地方传递null引用的约定。最终,是否使用Optional取决于每个API设计人员的选择。
参考资料:
- Should Java Getters Return Optional: https://stackoverflow.com/a/26328555/697630
- Java SE 8 Optional, a pragmatic approach: http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html