【问题标题】:Should you always use enums instead of constants in Java在 Java 中是否应该始终使用枚举而不是常量
【发布时间】:2008-12-14 22:44:44
【问题描述】:

在java

public class MyClass {
    public static int VERTICAL = 0;
    public static int HORIZONTAL = 1;

    private int orientation;

    public MyClass(int orientation) {
        this.orientation = orientation;
    }
...

你会这样使用它:

MyClass myClass = new MyClass(MyClass.VERTICAL);

现在,在 1.5 中,您显然应该使用枚举:

public class MyClass {
    public static enum Orientation {
        VERTICAL, HORIZONTAL;
    }

    private Orientation orientation;

    public MyClass(Orientation orientation) {
        this.orientation = orientation;
    }
...

现在你可以这样使用它:

MyClass myClass = new MyClass(MyClass.Orientation.VERTICAL);

我觉得有点难看。现在我可以轻松添加几个静态变量了:

public class MyClass {
    public static Orientation VERTICAL = Orientation.VERTICAL;
    public static Orientation HORIZONTAL = Orientation.HORIZONTAL;

    public static enum Orientation {
        VERTICAL, HORIZONTAL;
    }

    private Orientation orientation;

    public MyClass(Orientation orientation) {
        this.orientation = orientation;
    }
...

现在我可以再次这样做了:

MyClass myClass = new MyClass(MyClass.VERTICAL);

具有枚举的所有类型安全优点。

这是好的风格,坏的风格,还是两者都不是。你能想出更好的解决方案吗?

更新

Vilx- 是第一个强调我所缺少的东西的人——枚举应该是一等公民。在 java 中,这意味着它在包中拥有自己的文件——我们没有命名空间。本来以为会有点重量级的,但实际做了之后,感觉确实不错。

Yuval 的回答很好,但并没有真正强调非嵌套枚举。此外,至于 1.4 - JDK 中有很多地方使用整数,我真的在寻找一种方法来改进这种代码。

【问题讨论】:

  • 在第一个代码块中,您的意思是给每个变量一个不同的值,对吧?
  • 你真的需要 MyClass 类来做更多的事情,而不仅仅是不同的 Orientations 可以做的事情吗?

标签: java coding-style enums


【解决方案1】:

你太复杂了。让我们一起来看看吧。

发布 Java 1.5 你应该使用 Java Enum 类:

public enum Color
{
    BLACK, WHITE;
}

在 Java 1.5 之前,您应该使用类型安全的 Enum 模式:

public class Color
{
    public static Color WHITE = new Color("white");
    public static Color BLACK = new Color("black");

    private String color;

    private Color(String s)
    {
        color = s;
    }
}

这两种方式你都这样称呼它:

drawBackground(Color.WHITE);

具体来说,关于您的问题。这是代码风格的问题,但我认为首选方法是将枚举保留在它们单独的类中。尤其是当他们开始获得自己的方法时,例如getName()getId() 等......将其视为与普通类与匿名类相同的困境,一旦类开始变得混乱,就该移动它了输出到自己的文件中。

【讨论】:

    【解决方案2】:

    你知道你可以导入方向并说

    MyClass myClass = new MyClass(Orientation.VERTICAL);
    

    ?

    【讨论】:

    • 好点。是的,我做到了,但这仍然意味着调用代码更加冗长(它添加了一个导入行)。我的动机是让调用代码更短更简洁。
    • 对不起,伙计。我的意思是,我喜欢 Java 和所有的东西,但 更短 从来都不是这门语言的优先事项。
    • 更短?什么...所以你宁愿一遍又一遍地写 MyClass 而不是一个导入行?这对我来说既不短也不干净。
    【解决方案3】:

    不了解 Java,但在 .NET 中,好的做法是将枚举与使用它们的类并行放置,即使它仅由一个类使用。也就是说,你会写:

    namespace Whatever
    {
        enum MyEnum
        {
        }
        class MyClass
        {
        }
    }
    

    因此,您可以使用:

    MyClass c = new MyClass(MyEnum.MyValue);
    

    【讨论】:

      【解决方案4】:

      有一类重要的情况应该使用常量而不是enums。这是您想要使用常量进行算术运算或将它们与数值进行比较的时候。那么你真的需要intlongdouble

      相反,如果使用事物进行算术或数值比较永远没有意义,那么该事物应该是一个对象而不是原始数字,因此enum 会更合适。

      【讨论】:

        【解决方案5】:

        MyClass 上也可以有两个静态方法:

        MyClass.Vertical() : MyClass
        MyClass.Horizontal() : MyClass
        

        这些将返回一个具有正确枚举集的新实例。

        【讨论】:

          【解决方案6】:

          我同意你很有创意,但我认为这不是一个实用的解决方案,我认为你只是将“丑陋”转移到代码的不同部分。如果除了 VERTICAL 和 HORIZONTAL 之外,还有 DIAGONAL、AA、BB、CC 等,会发生什么?您是否必须通过键入每个静态常量来进行复制?您认为 MyClass.Orientation.VERTICAL 丑陋的品味可能是个人的?

          【讨论】:

          • 我同意我只是改变了丑陋,但我总是稍微喜​​欢它在被调用代码中而不是在调用代码中。这绝对是个人的,我什至不确定我是否喜欢另一种选择,这就是我寻求观点的原因。我得出的结论是最好单独上课。
          【解决方案7】:

          这取决于枚举可以取多少值。在您的示例中,只有两个,我只会使用布尔值。如果枚举仅由您编写的代码使用并且不必与许多其他代码交互,那么您可能不需要类型安全。但如果它采用“公共”方法,我肯定会选择枚举,并将枚举放在自己的文件中。

          【讨论】:

          • 你说得有道理,但使用枚举比布尔值更具自我描述性。
          • 但如果你只是将它传递给一个函数,那么你可以将签名设为“public MyClass(boolean isVertical)”。不过,这是我唯一会使用它的情况。
          猜你喜欢
          • 1970-01-01
          • 2011-10-22
          • 2021-06-10
          • 1970-01-01
          • 2013-02-09
          • 1970-01-01
          • 1970-01-01
          • 2016-01-18
          • 1970-01-01
          相关资源
          最近更新 更多