Java枚举与静态常量

我正在研究一些由公司其他部门维护的Java代码,偶然是一些以前的C和C ++开发人员。 无处不在的一件事是使用静态整数常量,例如

class Engine { private static int ENGINE_IDLE = 0; private static int ENGINE_COLLECTING = 1; ... } 

除了缺乏“最终”限定符之外,我对这种代码感到有点困扰。 我希望看到的是,从学校主要用Java培训,会更像是

 class Engine { private enum State { Idle, Collecting }; ... } 

然而,争论使我失望。 为什么,如果有的话,后者比前者更好?

为什么,如果有的话,后者比前者更好?

它更好,因为它为您提供类型安全性并且是自我记录的。 对于整数常量,您必须查看API文档以找出哪些值是有效的,并且没有什么可以阻止您使用无效值(或者更糟糕的是,完全不相关的整数常量)。 使用Enums,方法签名会直接告诉您哪些值有效(IDE自动完成将起作用),并且无法使用无效值。

遗憾的是,“整数常量枚举”模式非常常见,即使在Java标准API中(并从那里广泛复制),因为Java在Java 5之前没有枚举。

官方文档的摘录, http : //java.sun.com/j2se/1.5.0/docs/guide/language/enums.html :

这种模式有很多问题,例如:

  • 不是类型安全 – 因为一个季节只是一个int,你可以传递任何其他需要一个季节的int值,或者将两个季节加在一起(这没有任何意义)。
  • 无命名空间 – 您必须使用字符串(在本例中为SEASON_)为int枚举的常量添加前缀,以避免与其他int枚举类型冲突。
  • 脆弱性 – 因为int枚举是编译时常量,所以它们被编译到使用它们的客户端中。 如果在两个现有常量之间添加新常量或更改顺序,则必须重新编译客户端。 如果他们不是,他们仍然会运行,但他们的行为将是不确定的。
  • 打印的值是没有信息的 – 因为它们只是整数,如果你打印一个,你得到的只是一个数字,它不会告诉你它代表什么,甚至它不是什么类型。

而这只是涵盖它。 一个单词的论点是,枚举更具可读性和信息性。

还有一件事是枚举,就像课程一样。 可以有字段和方法。 这使您可以选择在枚举本身中包含有关每种类型状态的一些其他信息。

因为枚举提供类型安全。 在第一种情况下,您可以传递任何整数,如果使用枚举,则仅限于IdleCollecting

仅供参考: http : //www.javapractices.com/topic/TopicAction.do ?Id = 1 。

通过使用int来引用常量,您不会强迫某人实际使用该常量。 因此,例如,您可能有一个采用引擎状态的方法,有人可能会高兴地调用它:

 engine.updateState(1); 

使用enum 强制用户坚持使用解释性标签,因此它更清晰。

有一种情况是优选静态constance(而不是代码是遗留的,具有大量的依赖性),并且当该值的成员不是/可能以后不是有限时。

想象一下,如果你以后可以添加像Collected这样的新状态。 使用枚举执行此操作的唯一方法是编辑原始代码,如果在已经有很多代码操作它的情况下完成修改,则可能会出现问题。 除此之外,我个人认为没有理由不使用枚举。

只是我的想法。

  1. Readabiliy – 当您使用枚举并执行State.Idle ,读者立即知道您正在谈论空闲状态。 将其与4或5进行比较。

  2. 类型安全 – 当使用枚举时,即使错误地用户也不能传递错误的值,因为编译器将强制他使用枚举中的一个预先声明的值。 在简单整数的情况下,他甚至可以通过-3274。

  3. 可维护性 – 如果你想添加一个新状态Waiting ,那么通过在你的枚举状态中添加一个常量Waiting来添加新状态会很容易,而不会产生任何混淆。

Lajcik引用的规范的原因在Josh Bloch的Effective Java,第30项中有更详细的解释。如果你能访问那本书,我建议你仔细阅读。 Java Enums是完整的类,这就是为什么你得到编译时类型安全的原因。 你也可以给他们行为,给你更好的封装。

前者在1.5之前开始的代码中很常见。 实际上,另一个常见的习惯是在接口中定义常量,因为它们没有任何代码。

枚举也为您提供了极大的灵活性。 由于Enums本质上是类,您可以使用有用的方法来扩充它们(例如提供与枚举中的某个值对应的国际化资源字符串,在枚举类型的实例和可能需要的其他表示之间来回转换等。 )