代码之家  ›  专栏  ›  技术社区  ›  Christoffer

Java枚举与静态常数

  •  20
  • Christoffer  · 技术社区  · 15 年前

    我正在查看一些由公司其他部分维护的Java代码,顺便说一下以前的C和C++ DEVS。普遍存在的一件事是使用静态整数常量,例如

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

    除了缺少“final”限定符之外,我还有点为这种代码所困扰。我最想看到的是,在学校里主要从爪哇接受训练,这将是更像的事情。

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

    然而,这些争论使我失望。为什么后者比前者好呢?

    9 回复  |  直到 15 年前
        1
  •  24
  •   Michael Borgwardt    15 年前

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

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

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

        2
  •  8
  •   Lajcik    15 年前

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

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

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

    这就足以说明问题了。一个词的论点是,枚举只是更可读和信息量。

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

        3
  •  7
  •   fastcodejava    15 年前

    因为枚举提供类型安全性。在第一种情况下,可以传递任何整数,如果使用枚举,则限制为 Idle Collecting .

    FY: http://www.javapractices.com/topic/TopicAction.do?Id=1 .

        4
  •  5
  •   David Grant    15 年前

    通过使用 int 引用一个常数,并不是强迫某人实际使用这个常数。因此,例如,您可能有一个方法,它接受一个引擎状态,有人可能很乐意使用该状态调用:

    engine.updateState(1);
    

    使用一个 enum 军队 用户要坚持使用说明性标签,这样更清晰。

        5
  •  1
  •   NawaMan    15 年前

    在一种情况下,静态常量是首选的(而代码是具有大量依赖性的遗留代码),也就是说,该值的成员不是/以后可能不是有限的。

    想象一下,如果您以后可以添加新的状态 Collected . 对枚举进行修改的唯一方法是编辑原始代码,如果修改是在已有大量代码操作的情况下进行的,则可能会出现问题。除此之外,我个人认为没有理由不使用枚举。

    只是我的想法。

        6
  •  1
  •   Suraj Chandran    15 年前
    1. 再读 -当你使用Enums和Do时 State.Idle ,读者立即知道您正在谈论的是空闲状态。将其与4或5进行比较。

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

    3. 可维护性 -如果你想添加一个新的州 Waiting 然后,通过在枚举状态中添加一个常量waiting来添加新状态将非常容易,而不会引起任何混乱。
        7
  •  1
  •   Rob Thornton    15 年前

    从Josh Bloch的有效Java项目30中更详细地解释了规范的原因,即Lajik引号。如果你能读到那本书,我建议你仔细阅读。Java枚举是完全成熟的类,这就是为什么您可以获得编译时类型安全性的原因。您还可以为它们提供行为,从而提供更好的封装。

        8
  •  0
  •   Paul Tomblin    15 年前

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

        9
  •  0
  •   VoidPointer    15 年前

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