在地图中使用可选
好的,在我开始解释我的问题之前,我希望你知道我知道背后的设计思想,它不打算在字段或集合中使用,但我已经在Kotlin中编程了很多,真的不喜欢使用null
。
所以我有一个类似于虚幻引擎的基于节点的编辑器 ,每个节点都有ConnectionBox
es,它们可以是空闲的,或者被Connection
占用。
所以有不同的方法来表达这个使用映射每个ConnectionBox
到一个Connection
地图:
Map<ConnectionBox, Connection> connectionEndPoints;
如果ConnectionBox
是空闲的,则Connection
可以为null
。 我不喜欢这样,因为其他开发人员不知道这个Map的功能,并且它可能会返回null
现有的ConnectionBox
。
所以我很想用一个:
Map<ConnectionBox, Optional<Connection>> connectionEndPoints;
显示打算更好,你甚至可以读取它像:
“这个ConnectionBox
可能ConnectionBox
了一个Connection
。”
我的问题是:为什么我不应该这样做,尽管它显示的意图要清楚得多,并且阻止了NPE
。 每个SO-thread和每个博客文章都说这是不好的风格,甚至编译器都说我不应该这样做。
根据要求,这是一个SO线程,不鼓励使用Optional
作为字段或集合值: 用于可选
这里是警告(事实证明这是来自IntelliJ的警告):
警告:可选用作字段{fieldName}的类型
确定后,建议Connection
参考应该在ConnectioBox
的问题只是转移。
为什么是:
class ConnectionBox { Optional<Connection> connection; ...
比…更差
class ConnectionBox { Connection connection; //may be null ...
除非我发表评论,否则你不能看到你可能遇到NPE
,我不喜欢解释代码的评论,可以解释自己。
编辑
在观看Stuart Marks(在Oracle的JDK团队中为核心库团队工作)之后,从Devoxx 2016谈到“Optional – 所有Bikeshed的母亲” ,您应该跳到54:04 :
为什么不在字段中使用可选项?
- 更多的样式问题,而不是一个正确的问题
- 通常有一个更好的方法来建模缺少价值
- 在字段中使用可选字段通常是由于消除可空字段的奴仆愿望而产生的
- 记住,消除空值不是Optional的目标
- 在字段中使用可选…
- 为每个领域创造另一个对象
- 在读取的每个字段上引入内存中的相关负载
- 混乱你的代码
- 有什么好处? 连锁方法的能力?
原始帖子
根据IntelliJ的检查器(首选项>编辑器>检查>'可选'用作字段或参数类型):
可选的目的是为库方法返回类型提供一个有限的机制,需要有一个清晰的方法来表示“无结果”。 使用类型为
java.util.Optional
的字段也是有问题的,如果该类需要是可Serializable
,而java.util.Optional
不是。
这也适用于集合,如果你不得不序列化它们。 此外,看看这些链接:
-
Java 8可选:什么是重点?
所以回顾 – 为了摆脱NullPointerExceptions我们有一个新的类:
- 引发NullPointerExceptions
- 本身可以为null,导致NullPointerException
- 增加堆大小
- 使调试更加困难
- 使序列化对象,比如对于外部客户端来说是XML或JSON,要困难得多
-
为什么java.util.Optional被破坏
最后的讽刺是,通过试图劝阻空位,这个阶级的作者实际上鼓励了它的使用。 我确信有一些人会试图简单地从它们的函数中返回null来避免创建一个不必要和昂贵的可选引用,而不是使用正确的类型和组合器。
如果您关心可读性,还可以使用@Nullable
(在Eclipse以及IntelliJ中可用):
class ConnectionBox { @Nullable Connection connection; // ... }
或者,您可以创建一个可选的getter:
class ConnectionBox { Connection connection; // ... Optional<Connection> getConnection() { return Optional.ofNullable(connection); } }