枚举可以为每个常量都有一个构造函数

时间:2015-05-06 07:12:58

标签: java constructor enums effective-java

请查看此link。约书亚布洛赫在他的“有效Java”一书中说过

请注意,Operation常量从a放入stringToEnum映射中 在创建常量后运行的静态块。

  

尝试将每个常量本身从自己中添加到地图中   构造函数会导致编译错误

。这是一件好事,因为它会导致NullPointerException 如果它是合法的。

  

不允许枚举构造函数访问枚举的静态字段,   除了编译时常量字段。

这种限制是必要的 因为构造函数运行时尚未初始化这些静态字段。

我有两个问题

  1. 枚举可以为每个常量都有单独的构造函数吗?
  2. 为什么编译时常量字段可以在构造函数中访问而不是静态字段?
  3. 由于

3 个答案:

答案 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)

  1. 不,我认为这不是Bloch的意思,尽管它没有以最好的方式制定。 enum可以有构造函数,正如书中的enum Operation所示。 Bloch对“它自己的构造函数”的含义是:当Operation的构造函数运行该特定常量时。

  2. 上面引用的内容已经回答了这个问题:

      

    这个限制是必要的,因为当构造函数运行时,这些静态字段尚未初始化。

答案 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;
    }
}