如何定义枚举项的属性

iTE*_*Egg 53 java enums

我已经阅读了Java和C++之间的Enum差异问题但我仍然感到困惑.

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

public enum Checker {
    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");
}
Run Code Online (Sandbox Code Playgroud)

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

Sea*_*oyd 105

简答

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

构造函数

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

public enum King {
    ELVIS
}
Run Code Online (Sandbox Code Playgroud)

相当于

public enum King {
    ELVIS() // the compiler will happily accept this
}
Run Code Online (Sandbox Code Playgroud)

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

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

这是枚举上非常好的参考,也解释了构造函数问题.

字段和访问者

枚举是常量,因此是不可变的.但是,它们可以定义可以具有状态的字段.这是一个可怕的做法,因为开发商会希望枚举及其关联值是常量,但你可以仍然与getter和setter枚举定义一个非最终场.

这是合法的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;}
}
Run Code Online (Sandbox Code Playgroud)

但它可以实现这样的恶意代码:

String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);
Run Code Online (Sandbox Code Playgroud)

因此,在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下,它非常简单:你只需要一个字符串类型的字段(不可变),所以在构造函数中初始化它并提供一个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; }
}
Run Code Online (Sandbox Code Playgroud)

  • 该领域应该是'最终'. (5认同)
  • @mmyers:除了汤姆所说的,它也是记录意图的重要方式.没有理由该字段应该改变,它应该总是在构造函数完成后初始化,并且不应该允许它的设置.为什么不用含有恰好表达的关键字来记录. (3认同)
  • @mmyers奇怪但真实.它在JLS中.允许运行时进行优化,否则只会因为`final`而进行优化.但添加"final"的更好理由是有人可能想要阅读代码. (2认同)