使用私有静态成员在java中构造枚举

时间:2017-10-05 15:54:54

标签: java enums

考虑以下枚举构造:

public enum MyEnum {
    ENUM_A(TYPE1), ENUM_B(TYPE2), ENUM_C(TYPE1), ENUM_D(TYPE1);
    private static final String TYPE1 = "I am type 1";
    private static final String TYPE2 = "This is type 2";
    private final String type;
    private MyEnum(String type) {
        this.type = type;
    }
    public String getType() {
        return type;
    }
}

上面的代码无法编译,因为编译器抱怨illegal forward reference。我有点理解为什么因为常量是之后定义的。

然而,无法在枚举定义之上/之前移动常量,因为枚举限制/设计枚举定义必须是枚举类中的第一件事。

现在,如果代码更改为:

public enum MyEnum {
    ENUM_A(MyEnum.TYPE1), ENUM_B(MyEnum.TYPE2), ENUM_C(MyEnum.TYPE1), ENUM_D(MyEnum.TYPE1);
    private static final String TYPE1 = "I am type 1";
    private static final String TYPE2 = "This is type 2";
    private final String type;
    private MyEnum(String type) {
        this.type = type;
    }
    public String getType() {
        return type;
    }
}

然后它似乎有效。

我的问题是:即使编译后,更改的代码是否带有任何潜在问题?为什么更改可以解决编译器检查?这被认为是一种标准的方式或绕过可能在将来修复的编译器检查的方法吗?

3 个答案:

答案 0 :(得分:2)

这是一个完全可以接受的解决方案,我不会想到除了额外的混乱之外的任何缺点。

如果要删除混乱,可以使用interface可以保持常量值的事实。对于某些程序员来说,这可能会打破最少的意外,但我会在我的代码中接受它。

private interface MyConstants {
    String TYPE1 = "I am type 1";
    String TYPE2 = "This is type 2";
}

public enum MyEnum implements MyConstants{
    ENUM_A(TYPE1), ENUM_B(TYPE2), ENUM_C(TYPE1), ENUM_D(TYPE1);
    private final String type;
    private MyEnum(String type) {
        this.type = type;
    }
    public String getType() {
        return type;
    }
}

答案 1 :(得分:1)

有一个问题,是的。

通过规避不使用尚未声明的字段的限制(通过引用声明这些静态字段的类,这可能不是当前类,因此绕过编译器验证已经声明了这些字段),在它们存在之前使用这些字段。

它在你的例子中工作正常,因为你的字段碰巧是常量:它们是字符串文字声明为final。因此,编译器在编译时知道它们的值,并用MyEnum.TYPE1的已知常量值替换MyEnum.TYPE1。

如果你的字段非常不变,它将停止工作,但它仍然会编译,并且只在运行时提供不需要的结果。例如,尝试:

private static final String TYPE1 = new String("I am type 1");

不再是常数=>不再工作了。

答案 2 :(得分:1)

或者,您可以将枚举放在常规类中,并在枚举旁边将常量声明为类成员。

public class ConstantTypes {

   private static String type1 = "type 1"
   private static String type2 = "type 2"

   public enum Types {
      A(type1) {},
      B(type1) {},
      C(type2) {},
      D(type2) {};
      private final String type;
      private Types(String typ) {
          type = typ;
      }
      public String getType() { return type; }
   }
}

编辑:要直接回答您的问题,您在第二个代码示例中并不完全“正在解决编译器检查”问题。在那里,您以“静态方式”访问静态值,而在第一个示例中,您不是。我的第二个例子(除了可读性之外)没有潜在的问题,代码编译,你很好。