是否应该为 Java 枚举定义 null/unknown 值?

2022-09-01 03:18:22

当您为接口中可能“未定义”的内容定义枚举时,您应该

  • 为此定义一个单独的枚举值,或者
  • 只是使用enumValue = null来表示这些情况?

例如

服务X.set价格(价格价格枚举)

enum Price {
 CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN
}

和 priceEnum.UNKNOWN(需要时未知)

enum Price {
 CHEAP, EXPENSIVE, VERRRY_EXPENSIVE
}

和 priceEnum = null(需要时)?

对此进行一些辩论。我想到的一些要点:

  • 使用 Price.UNKNOWN 会保存一些“if (price == null)”代码。您可以在单个开关箱中处理价格 x 的所有值
  • 根据视图技术的不同,本地化 Price 可能会更容易。
  • 使用Price.UNKNOWN会导致代码IMO中的“幻数”问题。在这里我们有Price.UNKNOWN,其他地方可能是Color.UNDEFINED,Height.NULLVALUE等
  • 使用 priceValue = null 与 Java 中其他数据类型的处理方式更加一致。对于未知值,我们有整数 i = null,DomainObject x = null,字符串 s = null,不是吗?
  • Price.UNKNOWN 强制您决定是否允许所有用例的空值。我们可能有方法 Price getPrice() 它可能返回 Price.UNKNOWN 和 setPrice(Price p),不允许接受 Price.UNKNOWN。由于 Price.UNKNOWN 始终包含在枚举的值中,因此这些接口看起来有点不干净。我知道 priceValue = null 也有同样的问题(您无法在界面中定义 null 是否被接受),但它感觉更干净一些,误导性也更少(?)

答案 1

这实际上是应用 Null 对象模式的一个示例。恕我直言,最好有一个虚拟对象而不是空。例如,您可以将虚拟方法添加到 null 对象中,而不是将代码分散到各处进行空检查。非常 方便 。

另外,名称也给了你一些额外的语义:价格是未知的,未定义的,不值得信赖的,还不知道吗?如果价格为,这意味着什么?enum

更新:正如 Aaron Digulla 所指出的,Null Object 模式需要内存。但实际上大多数时候情况并非如此。在传统实现中,通常到处都使用 Null 对象的单例,因为不需要单独的实例。枚举会变得更好,因为您可以免费获得单例语义。

另一点是,对某个对象的引用和引用占用相同的内存量(例如,在32位机器上为4个字节)。它是被引用的对象占用了一些额外的内存。但是,如果这是一个单例,则此处几乎没有内存开销。null


答案 2

我会说,如果这是一个价格的有效值,那就去吧。Price.UNKNOWN

我同意您提到的处理空引用的缺点,并且我认为它们足以激励决策。

新语言,以Scala为例(以及一些较旧的语言,Haskell)一起远离空引用,而是使用选项/也许是monads......这是有充分理由的。