我正在研究一些由公司其他部门维护的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 };
...
}
然而,这些论点让我失望。为什么,如果有的话,后者比前者更好?
答案 0 :(得分:24)
为什么,如果有的话,后者更好 比前者?
它更好,因为它为您提供类型安全性并且是自我记录的。对于整数常量,您必须查看API文档以找出哪些值有效,并且没有什么可以阻止您使用无效值(或者更糟糕的是,完全不相关的整数常量)。使用Enums,方法签名会直接告诉您哪些值有效(IDE自动完成将起作用),并且无法使用无效值。
遗憾的是,“整数常量枚举”模式很常见,即使在Java标准API中(并从那里广泛复制),因为Java在Java 5之前没有枚举。
答案 1 :(得分:8)
摘自官方文档,http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html:
这种模式存在许多问题,例如:
- 非类型安全 - 因为一个季节只是一个int,你可以传递任何其他需要季节的int值,或者将两个季节加在一起(这没有任何意义)。
- 无命名空间 - 您必须使用字符串(在本例中为SEASON_)为int枚举的常量添加前缀,以避免与其他int枚举类型发生冲突。
- 脆弱性 - 因为int枚举是编译时常量,所以它们被编译到使用它们的客户端中。如果在两个现有常量之间添加新常量或更改顺序,则必须重新编译客户端。如果他们不是,他们仍将继续运行,但他们的行为将是不确定的。
- 印刷值没有信息 - 因为它们只是一个整体,如果你打印出一个,你得到的只是一个数字,它不会告诉你它代表什么,甚至它不是什么类型。
这只是涵盖它。一个单词的论点是,枚举更具可读性和信息性。
还有一件事就是枚举,就像课程一样。可以有字段和方法。这使您可以选择在枚举本身中包含有关每种状态类型的一些其他信息。
答案 2 :(得分:7)
因为枚举提供了类型安全性。在第一种情况下,您可以传递任何整数,如果您使用枚举,则仅限Idle
和Collecting
。
仅供参考:http://www.javapractices.com/topic/TopicAction.do?Id=1。
答案 3 :(得分:5)
通过使用int
来引用常量,您不会强迫某人实际使用该常量。因此,例如,您可能有一个采用引擎状态的方法,有人可能会高兴地调用它:
engine.updateState(1);
使用enum
强制用户坚持使用解释性标签,因此更加清晰。
答案 4 :(得分:1)
有一种情况是首选静态constance(而不是代码是遗留的,具有大量的依赖性),并且当该值的成员不是/可能以后不是有限时。
想象一下,如果您以后可以添加像Collected
这样的新状态。使用枚举执行此操作的唯一方法是编辑原始代码,如果在已经有很多代码操作它的情况下完成修改,则可能会出现问题。除此之外,我个人认为没有理由不使用枚举。
只是我的想法。
答案 5 :(得分:1)
Readabiliy - 当您使用枚举并执行State.Idle
时,读者会立即知道您正在谈论空闲状态。将其与4或5进行比较。
类型安全 - 使用枚举时,即使错误,用户也无法传递错误的值,因为编译器会强制他使用枚举中的一个预先声明的值。在简单整数的情况下,他甚至可以通过-3274。
Waiting
,那么通过在枚举状态中添加常量等待而不会产生任何混淆来添加新状态将非常容易。 答案 6 :(得分:1)
Lajcik引用的规范的原因,在Josh Bloch的Effective Java,第30项中有更详细的解释。如果你能访问那本书,我建议你仔细阅读。 Java Enums是完整的类,这就是为什么你得到编译时类型安全的原因。你也可以给他们行为,给你更好的封装。
答案 7 :(得分:0)
前者在1.5之前开始的代码中很常见。实际上,另一个常见的习惯是在界面中定义你的常量,因为它们没有任何代码。
答案 8 :(得分:0)
Enums还为您提供了极大的灵活性。由于Enums本质上是类,您可以使用有用的方法来扩充它们(例如,提供与枚举中的某个值对应的国际化资源字符串,在枚举类型的实例和可能需要的其他表示之间来回转换,等等。 )