【问题标题】:Access other enums in enum's constructor在枚举的构造函数中访问其他枚举
【发布时间】:2011-07-03 23:30:17
【问题描述】:

我需要类似下面的东西

enum EE {
    A("anything"),
    B("beta"),
    ...
    Z("zulu"),
    ALL,
    ;

    EE(String s) {
        this.s = s;
    }
    EE() {
        String s = "";
        for (EE ee : values()) { // PROBLEM HERE
            if (ee != ALL) s += " " + ee.s;
        }
        this.s = s;
    }
}

在创建ALL 时,我想访问枚举的其他成员。由于此时values() 返回null,上述方法不起作用。显式使用 AB、...、Z 不会编译。我完全理解为什么会发生这种先有鸡的问题,但我正在寻找一个好的解决方法。

不,从EE 中删除ALL 不是一种选择。

【问题讨论】:

    标签: java oop enums initialization


    【解决方案1】:

    这对你有用吗? :

    enum EE {
        A("anything"),
        B("beta"),
        ...
        Z("zulu"),
        ALL,
        ;
    
        String s = null;
    
        EE(String s) {
            this.s = s;
        }
    
        EE() {
        }
    
        private void initS() {
            String s = "";
            for (EE ee : values()) { 
                if (ee != ALL) s += " " + ee.s;
            }  
    
            this.s = s;
        }
    
        public String getS() {
           if ( this.s == null )  { // assume we are ALL and initialize
             initS();
           }
    
           return this.s;
        }
    }
    

    静态初始化器可能更干净。

    public enum EE {
        A("anything"),
        B("beta"),
        Z("zulu"),
        ALL
        ;
    
        static {
            String s = "";
            for (EE ee : values()) {
                if ( ee != ALL ) s += ee + " ";
            }
    
            ALL.s = s.trim();
        }
    
        String s = null;
    
        EE(String s) {
            this.s = s;
        }
    
        EE() {
        }
    }
    

    【讨论】:

    • 我想会的。我不喜欢懒惰的初始化,但我可以把它移到一个静态块中。
    • 后期绑定来拯救。
    【解决方案2】:

    您可以有一个静态 StringBuilder,每个枚举常量都将其值附加到构造函数中,然后在默认构造函数中将枚举的字符串设置为 StringBuilder 的值。

    但是请注意,Java 会阻止您直接从枚举的构造函数访问静态变量(这是有充分理由的!),因此您必须在另一个方法中完成脏活,然后从构造函数中调用它。

    为此,您必须确保最后声明 ALL

    作为免责声明,尽管这确实是一种可怕的解决方法,如果可以的话,我鼓励您在这里探索其他可能性!

    【讨论】:

    • 其实我的情况有点复杂,但我总是只参考前面的元素。不幸的是,StringBuilder 不能是静态类成员,否则这个解决方案将是完美的。
    【解决方案3】:

    最好的方法之一是使用enum polymorphism technique

    public enum EE {
        A("anything"), B("beta"), Z("zulu"), ALL {
    
            @Override
            public String getS() {
                if (super.s == null) {
                    String s = "";
                    for (EE ee : values()) {
                        if (ee != ALL) {
                            s += " " + ee.s;
                        }
                    }
                }
                return s;
            }
        },
        ;
    
        private String s;
    
        EE(String s) {
            this.s = s;
        }
    
        EE() {
            this.s = null;
        }
    
        public String getS() {
            return this.s;
        }
    }
    

    测试类:

    public class TestEE {
    
        public static void main(String[] args) {
            for (EE ee : EE.values()) {
                System.out.println(ee.name() + ": " + ee.getS());
            }
        }
    }
    

    另见:

    【讨论】:

    • 它确实有效,但它引入了一些运行时开销。这可能无关紧要。
    • @maaartinus 将运行时开销从每次减少到一次,我猜这已经足够小了。
    【解决方案4】:

    为什么不能全部删除?

    考虑使用EnumSet,这将为您提供 EE 的任意组合。

    import java.util.*;
    enum EE {
        A("anything"), B("beta"), Z("zulu");
        EE(String s) {
            this.s = s;
        }
        static Set<EE> all=EnumSet.allOf(EE.class);
        final String s;
    }
    

    【讨论】:

    • 我需要得到ALLALL.s = "anything beta ... zulu",这里没有EnumSet 可以提供帮助。此外,我将像使用EE 的所有其他成员一样使用ALL
    猜你喜欢
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    相关资源
    最近更新 更多