【发布时间】:2010-06-16 14:33:32
【问题描述】:
我已经阅读了Difference of Enum between java and C++? 的问题,但我仍然感到困惑。
我希望以下返回相关的字符串:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
}
根据我的阅读,这应该是可能的。只是希望您对如何实现它有所了解。
【问题讨论】:
我已经阅读了Difference of Enum between java and C++? 的问题,但我仍然感到困惑。
我希望以下返回相关的字符串:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
}
根据我的阅读,这应该是可能的。只是希望您对如何实现它有所了解。
【问题讨论】:
您需要一个构造函数、一个字段和一个 getter。
枚举类型可以有构造函数,前提是它们的访问级别是私有的或默认的(包私有)。您不能直接调用这些构造函数,除非在枚举声明本身中。与类类似,当你定义一个不带参数的枚举常量时,实际上是调用了编译器生成的默认构造函数。例如
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 的枚举中定义非最终字段。
这是合法的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% 的情况下:如果您的枚举中有字段,您应该将它们设为 final 并仅提供 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; }
}
【讨论】:
final 而进行优化。但添加final 的更好理由是有人可能想阅读代码。
如果模式成立,这也有效并消除了重复:
public enum Checker {
EMPTY,
RED,
YELLOW;
public String getDescription(){
String name = name();
return ""+Character.toUpperCase(name.charAt(0))
+name.substring(1).toLowerCase();
}
}
【讨论】:
String 是否总是以它们天真出现的方式相关。你可能想要FUSCHIA("Fuchsia"), WTF("Dusty Lavendar")。