Access other enums in enum's constructor

2019-02-18 07:45发布

I'd need something like the following

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

While creating ALL I'd like to access the other members of the enum. The above doesn't work because of values() returning null at this point. Using A, B, ..., Z explicitly doesn't compile. I understand perfectly why this chicken-egg problem happens, but am looking for a nice workaround.

And no, removing ALL from EE is not an option.

4条回答
老娘就宠你
2楼-- · 2019-02-18 08:13

One of the best ways would be using the 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;
    }
}

Test class:

public class TestEE {

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

See also:

查看更多
地球回转人心会变
3楼-- · 2019-02-18 08:15

why can't you remove all?

consider using EnumSet, this will give you any combination of the EE's.

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;
}
查看更多
Luminary・发光体
4楼-- · 2019-02-18 08:21

Would this work for you? :

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

Static initializer might be cleaner.

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() {
    }
}
查看更多
ら.Afraid
5楼-- · 2019-02-18 08:31

You could have a static StringBuilder that each enum constant appends its value to in the constructor, then in your default constructor just set the enum's string to the value of the StringBuilder.

Note however that Java will prevent you accessing static variables directly from an enum's constructor (for good reason!) so you'll have to do the dirty work in another method and then call that from the constructor.

For this to work though you'll have to make sure ALL is declared last.

As a disclaimer though this is a truly horrible workaround and if you can at all, I'd encourage you to explore other possibilities here!

查看更多
登录 后发表回答