好的,在我开始解释我的问题之前,我想让你知道我知道背后的设计理念Optional,它不打算用于字段或集合,但我已经在Kotlin编程了很多,并且真的不喜欢使用null.
所以我在虚幻引擎中有一个基于节点的编辑器,每个节点都有ConnectionBoxes,它可以是空闲的,也可以被a占用Connection.
因此,有不同的方式来表达这其中之一是利用一张地图,每一个映射ConnectionBox到一个Connection这样的:
Map<ConnectionBox, Connection> connectionEndPoints;
Run Code Online (Sandbox Code Playgroud)
而Connection可能是null,如果ConnectionBox是免费的.我不喜欢这个,因为其他开发人员不知道这个Map的功能,并且它可能会返回null现有的ConnectionBox.
所以我很想用一个:
Map<ConnectionBox, Optional<Connection>> connectionEndPoints;
Run Code Online (Sandbox Code Playgroud)
它显示出更好的打算,你甚至可以读出它:
"这ConnectionBox可能有Connection附加的."
我的问题是:为什么我不应该这样做,即使它更明确地表明意图并阻止NPEs.每个SO帖子和每个博客文章都说这是糟糕的风格,甚至编译器也说我不应该发出警告.
根据要求,这里是一个SO线程,不鼓励使用Optional作为字段或集合值:用于可选
这是警告(因为事实证明它是来自IntelliJ的警告):
警告:可选用作字段{fieldName}的类型
好之后,建议Connection引用应该在ConnectioBox问题的范围内转移.
为什么是:
class ConnectionBox {
Optional<Connection> connection;
...
Run Code Online (Sandbox Code Playgroud)
比...更差
class ConnectionBox {
Connection connection; //may be null
...
Run Code Online (Sandbox Code Playgroud)
除非我发表评论,否则您无法看到您可能会遇到NPE并且我不喜欢解释可以解释自己的代码的评论.
在观看了 Stuart Marks(在 Oracle JDK 小组的核心库团队工作)在 Devoxx 2016 上演讲“Optional \xe2\x80\x93 The Mother of All Bikesheds”之后,您应该跳到54:04:
\n\n\n\n\n为什么不在字段中使用可选?
\n\n\n
\n- 更多的是风格问题而不是正确性问题\n \n
\n\n
- 通常有更好的方法来模拟值的缺失
\n- 在字段中使用Optional通常是出于消除可为空字段的盲目愿望
\n- 请记住,消除空值不是可选的目标
\n- 在字段中使用可选...\n \n
\n\n
- 为每个字段创建另一个对象
\n- 在每个字段读取时引入内存的相关负载
\n- 让你的代码变得混乱
\n- 有什么好处?能够链接方法吗?
\n
根据 IntelliJ 的检查器(首选项 > 编辑器 > 检查 > 用作字段或参数类型的“可选”):
\n\n\n\n\n可选的设计目的是为库方法返回类型提供有限的机制,其中需要有一种明确的方式来表示“无结果”。
\njava.util.Optional如果类需要为,则使用具有类型的字段也会出现问题Serializable,但事实java.util.Optional并非如此。
这也适用于集合,以防您必须序列化它们。此外,请查看这些链接:
\n\n\n回顾一下 - 为了摆脱 NullPointerExceptions,我们有一个新类:
\n\n
\n\n
\n- 抛出空指针异常
\n- 本身可以为 null,从而导致 NullPointerException
\n- 增加堆大小
\n- 使调试变得更加困难
\n- 使序列化对象(例如外部客户端的 XML 或 JSON)变得更加困难
\n
\n最后一个讽刺的是,通过试图阻止 null,该类的作者实际上鼓励了它的使用。我确信有些人会试图简单地从函数中返回 null,以便“避免创建不必要且昂贵的可选引用”,而不是使用正确的类型和组合器。
\n
如果您关心可读性,您还可以使用@Nullable(在Eclipse和IntelliJ中可用):
class ConnectionBox {\n @Nullable\n Connection connection;\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n\n或者,您可以创建一个可选的 getter:
\n\nclass ConnectionBox {\n Connection connection;\n // ...\n Optional<Connection> getConnection() {\n return Optional.ofNullable(connection);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n