请查看此link。约书亚布洛赫在他的“有效Java”一书中说过
请注意,Operation常量从a放入stringToEnum映射中 在创建常量后运行的静态块。
尝试将每个常量本身从自己中添加到地图中 构造函数会导致编译错误
。这是一件好事,因为它会导致NullPointerException 如果它是合法的。
不允许枚举构造函数访问枚举的静态字段, 除了编译时常量字段。
这种限制是必要的 因为构造函数运行时尚未初始化这些静态字段。
我有两个问题
由于
答案 0 :(得分:5)
至于第一个问题:你不能拥有单独的构造函数,但是你可以通过以下方式解决这个问题:
public enum EnumTest {
ONE() {
void init() {
val = 2;
}
},
TWO() {
void init() {
val = 1;
}
};
protected int val;
abstract void init();
EnumTest() {
init();
}
}
这样,从技术上讲,您可以为不同的常量使用单独的初始化方法。
另一种方法是使用初始化部分:
public enum EnumTest {
ONE() {{
val = 2;
}},
TWO() {{
val = 1;
}};
protected int val;
}
至于你的第二个问题:在枚举构造期间无法访问常量字段,因为静态字段可以访问枚举常量。例如,此代码正确编译:
public enum EnumTest {
ONE, TWO;
public static final String ONE_STRING = ONE.toString();
}
如果允许从构造函数访问ONE_STRING,您可能会有无限的初始化循环或访问尚未初始化的枚举常量。
答案 1 :(得分:4)
不,我认为这不是Bloch的意思,尽管它没有以最好的方式制定。 enum
可以有构造函数,正如书中的enum Operation
所示。 Bloch对“它自己的构造函数”的含义是:当Operation
的构造函数运行该特定常量时。
上面引用的内容已经回答了这个问题:
这个限制是必要的,因为当构造函数运行时,这些静态字段尚未初始化。
答案 2 :(得分:2)
适用于构造函数的常规规则。只要具有不同的签名,您可以拥有任意数量的构造函数。然后可以使用不同的构造函数构建不同的enum
值:
enum StringAndNumber {
Zero("zero"),
Five(5),
Pi("Pi", 3.14159);
private final String str;
private final Number num;
private StringAndNumber(String str) {
this.str = str;
this.num = null;
}
private StringAndNumber(Number num) {
this.num = num;
this.str = null;
}
private StringAndNumber(String str, Number num) {
this.str = str;
this.num = num;
}
}