Java 枚举与静态常量

2022-09-02 05:35:43

我正在查看一些由公司其他部门维护的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 };
    ...
}

但是,这些论点让我失望了。为什么后者比前者更好?


答案 1

为什么后者比前者更好?

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

不幸的是,“整数常量枚举”模式非常普遍,即使在Java Standard API中也是如此(并且从那里广泛复制),因为Java在Java 5之前没有枚举。


答案 2

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

此模式存在许多问题,例如:

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

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

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