Java 何时使用枚举?

Java 何时使用枚举?,java,enums,Java,Enums,我有一个例子(在Java中),其中有一些模型,每个模型都具有相同的类型集。我将类型定义为枚举。当我向顾问介绍这个程序(这是一个项目)时,他说使用枚举是不明智的,因为它使程序无法灵活地进行更改,因为枚举是不可扩展的。因此,如果我想在某个时候添加另一个类型,我不能不重新编译就这样做。是否曾经有过这样一种情况,您更喜欢枚举而不是创建对象?在我看来,如果你能在一个带有对象的灵活类和一个带有枚举的非灵活类之间做出选择,你最好每次都使用对象,即使你“99%”确信类型永远不会改变。每当一个对象有有限的可能状态

我有一个例子(在Java中),其中有一些模型,每个模型都具有相同的类型集。我将类型定义为枚举。当我向顾问介绍这个程序(这是一个项目)时,他说使用枚举是不明智的,因为它使程序无法灵活地进行更改,因为枚举是不可扩展的。因此,如果我想在某个时候添加另一个类型,我不能不重新编译就这样做。是否曾经有过这样一种情况,您更喜欢枚举而不是创建对象?在我看来,如果你能在一个带有对象的灵活类和一个带有枚举的非灵活类之间做出选择,你最好每次都使用对象,即使你“99%”确信类型永远不会改变。

每当一个对象有有限的可能状态时,你都会使用枚举。每次,不管你的上司说什么。是的,看看这个:


使用枚举改进了静态/编译时分析。只能使用指定的枚举

这是否好取决于图书馆是供内部还是外部使用

对于内部消费,重新编译不是问题。您可以访问源代码,您可以随时添加其他值。
enum
的一部分值是它提供给您的编译器时间检查,因此在这种情况下重新编译是一件好事

对于外部消费,您必须更加小心。您必须更加自信,因为没有支持的理由来增加其他价值。(可能有理由扩展这些值,但如果这些值不受支持,它们无论如何也不能这样做)您的库的用户不希望/可能无法仅仅为了添加一些功能而重新编译您的库

我所做的是尽量做到两全其美

  • 我定义并使用一个接口
  • 我有枚举实现
这允许您使用枚举,但允许库用户定义自己的实现,这些实现可以是自己的枚举,也可以是动态创建的实例


下面是一个接口的枚举示例,该接口可以扩展,但没人可以扩展

公共枚举StopCharTester实现StopCharTester{
逗号站{
@凌驾
公共布尔值isStopChar(int-ch){
返回ch<''| ch==',';
}
},控制站{
@凌驾
公共布尔值isStopChar(int-ch){
返回ch<'';
}
},
空间站{
@凌驾
公共布尔值isStopChar(int-ch){
返回字符。isWhitespace(ch)| | ch==0;
}
},
XML_文本{
@凌驾
公共布尔值isStopChar(int-ch){
返回ch=''“| | ch=''| | ch==0;
}
},
固定文本{
@凌驾
公共布尔值isStopChar(int-ch){
返回ch
  • 当枚举的成员永远无法更改时,您更喜欢枚举。例如,如果您正在开发国际象棋程序,您可以绝对确保国际象棋棋子列表永远不会更改
  • 更改枚举成员时,需要对代码进行其他更改。例如,如果枚举提供加密算法,则不能仅添加新算法。您必须实现它。这意味着您的程序无论如何都必须重新编译。请注意,此规则不是绝对的:您可以创建发现可用实现的程序动态地定义特定接口的n

  • 可能与我以前看到的@deb_rider重复。我遇到的问题是枚举与对象相比较,而不是静态变量(常量)。如果创建一个对象类,则可以有一个类月份的对象和一个类周的对象。这样,您就不会有问题,例如尝试将周一与一月进行比较,或者执行周一+1==二月之类的操作。如果您的库具有内置假设,则一年中正好有12个月,则无法提供添加月份的功能在没有重新编译的情况下工作。你想限制用户使用可以工作的选项。假设我做了一个国际象棋游戏,得到了普通的棋子(国王、王后……)在某种程度上,有人决定通过在每边增加两列来扩展棋盘游戏。这不再是传统标准的棋盘游戏,而是对现有概念的扩展;如果我们使用Enum,就不可能添加新类型的棋子。我看到过一些例子,其中北、西、东、南的方向是相同的声明为枚举。那么你就不能去西北。在我看来,你永远无法预测你的程序在未来几年内将如何使用。(尽管与我的项目范围无关)我可以预测国际象棋永远不会有新棋子。我还可以预测,如果你调用enum
    BasicGeoDirections
    ,它将永远不会被扩展,因为
    NORTHWEST
    不是一个基本方向。谢谢你的回答!我认为使用接口也是最好的方式,因为你提到了它。即使你确定enum是y你已经决定了你永远都不会改变,意外的事情可能在将来的某个地方发生;因此,拥有扩展选项对imo来说总是很方便的。@Babyburger我在很多枚举从未被“扩展”过的情况下都这样做过。这没有什么坏处。@Babyburger我添加了一个例子。
    public enum StopCharTesters implements StopCharTester {
        COMMA_STOP {
            @Override
            public boolean isStopChar(int ch) {
                return ch < ' ' || ch == ',';
            }
        }, CONTROL_STOP {
            @Override
            public boolean isStopChar(int ch) {
                return ch < ' ';
            }
        },
        SPACE_STOP {
            @Override
            public boolean isStopChar(int ch) {
                return Character.isWhitespace(ch) || ch == 0;
            }
        },
        XML_TEXT {
            @Override
            public boolean isStopChar(int ch) {
                return ch == '"' || ch == '<' || ch == '>' || ch == 0;
            }
        },
        FIX_TEXT {
            @Override
            public boolean isStopChar(int ch) {
                return ch <= 1;
            }
        };