如何定义枚举项的属性

时间:2010-06-16 14:33:32

标签: java enums

我已经阅读了问题Difference of Enum between java and C++?,但我仍感到困惑。

我希望以下内容返回相关的字符串:

public enum Checker {
    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");
}

从我所读到的,这应该是可能的。只是希望你对如何实现它有所了解。

2 个答案:

答案 0 :(得分:102)

简答

你需要一个构造函数,一个字段和一个getter。

构造

枚举类型可以有构造函数,只要它们的访问级别是私有或默认(包私有)。除了在枚举声明本身之外,您不能直接调用这些构造函数。与类类似,当您定义不带参数的枚举常量时,实际上是调用编译器生成的默认构造函数。 E.g。

public enum King {
    ELVIS
}

相当于

public enum King {
    ELVIS() // the compiler will happily accept this
}

就像在类中一样,如果你定义一个显式的构造函数,编译器将不会插入一个默认的构造函数,所以这不会编译:

public enum King {
    ELVIS, // error, default constructor is not defined
    MICHAEL_JACKSON(true)
    ;
    private boolean kingOfPop;
    King(boolean kingOfPop){this.kingOfPop = kingOfPop;}
}

这是a pretty good reference on enums,也解释了构造函数问题。

字段和访问者

枚举是常量,因此是不可变的。但是,它们可以定义可以具有状态的字段。这是一个糟糕的做法,因为开发人员会希望枚举及其相关值是常量,但 仍然可以在枚举中使用getter和setter来定义非final字段。

这是合法的java代码:

public enum Color {
    RED("FF0000"),
    GREEN("00FF00"),
    BLUE("0000FF");
    private String code;
    public String getCode(){return code;}
    public void setCode(String code){this.code = code;}
    private Color(String code){this.code = code;}
}

但它可以启用这样的恶意代码:

String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);

因此在99.99%的情况下:如果您的枚举中有字段,则应将其设为最终字段并仅提供getter。如果字段本身不是不可变的,请提供防御性副本:

public enum Band {
    THE_BEATLES("John","Paul","George","Ringo");
    private final List<String> members;
    public List<String> getMembers(){
        // defensive copy, because the original list is mutable
        return new ArrayList<String>(members);
    }
    private Band(String... members){
        this.members=Arrays.asList(members);
    }
}

解决方案

在你的情况下,它非常简单:你只需要一个字符串类型的字段(不可变),所以在构造函数中初始化它并提供一个getter是完全可以的:

public enum Checker {

    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");

    private final String value;

    private Checker(final String value) {
        this.value = value;
    }

    public String getValue() { return value; }
}

答案 1 :(得分:4)

如果模式成立,这也有效并消除了重复:

public enum Checker {
    EMPTY,
    RED,
    YELLOW;


    public String getDescription(){
        String name = name();
        return ""+Character.toUpperCase(name.charAt(0))
                 +name.substring(1).toLowerCase();
    }

}