我正在处理一些有关我使用了部分模型的不安全(无类型安全)字符串或整数表示的地方的工作,
并利用Enum和EnumSet最佳实践。

一个特殊的困难是这种用例:一个枚举,其中每个实例都拥有自己姐妹的[0..n]的EnumSet。

为了简化要点,我将我的问题基于约书亚·布洛赫(Joshua Bloch)的StyleEnum。因此,我们得到了一个BOLD,ITALIC,UNDERLINE,STRIKETHROUGH ..的枚举。让我们想象一个B_AND_I,它将保存{BOLD,ITALIC}。

请不要使用毫无意义的示例:在实际系统中,此subSet是基于在启动时间加载的一些更改规则构建的。

目标是一旦进行了这种计算,就无法更改实例特定的子EnumSet范围。
所以我来了这样的事情:

public enum StyleEnum {
    NONE(0, "none"), BOLD(100, "B"), ITALIC(250, "i"), UNDERLINE(350, "u"), STRIKETHROUGH(9, "b"), B_AND_I(99,"Emphase");

//// Pure dream  ==   private final EnumSet<StyleEnum> complexComputedSubSet = new EnumSet<StyleEnum> ();
//// But not in the jdk
    private final EnumSet<StyleEnum> complexComputedSubSet;
    private final int intProp;
    private final String strLabel;

    StyleEnum(int intProp, String strLabel) {
        this.intProp = intProp;
        this.strLabel = strLabel;
//// option 2 would have been be this
//        complexComputedSubSet = EnumSet.of(NONE);
//// But COMPILER :: illegal reference to static field from initializer

    }//.... end of constructor


    /**
     * static initialzer will compute based on some rules a subset of (none) or
     * others Enum, a particular enum instance can holds in his bag.
     */
    static {
//// at least, as option 3, why not this...
//        for (StyleEnum e : EnumSet.allOf(StyleEnum.class)) {
//            e.complexComputedSubSet = EnumSet.of(NONE);
//        }
//// COMPILER :: cannot assign a value to final variable complexComputedSubSet

        // main handling here : at class loading
        // compute a set (rules coming from whatever you want or can).
        //Once this static class level init is done
        // nothing can change the computed EnumSet
        // it's getter will always return an unmodifiable computed EnumSet
        //.... computing something
    }


    //....
    //getter(){}
    //whateverelse(){}

}


如您所见,这里没有什么是真正令人愉快或至少优雅的。

在我的梦里 :

private final EnumSet<StyleEnum> complexComputedSubSet= new EnumSet<StyleEnum> ();
//..
//static initialzer
static {
    EnumSet.allOf(StyleEnum.class).forEach(e-> computeSubSet(e));
//..
}
private static void computeSubSet(StyleEnum instance){
    //...
    instance.complexComputedSubSet.addAll(someComputedCollection);
}


等等!

取而代之的是,我所能做的似乎都无法赢得决赛

 // getting away from the final keyword
 private EnumSet<StyleEnum> complexComputedSubSet;


然后在类的静态初始化程序块循环中,并使用仅出于此(愚蠢)目的而引入的(虚拟)标记(无)进行实例化:

       for (StyleEnum e : EnumSet.allOf(StyleEnum.class)) {
           e.complexComputedSubSet = EnumSet.of(NONE);
       }


并且只有在那之后计算并存储子EnumSet。

因此,所有这一切的痛苦-主要是-,只是因为一个人不能说“ new EnumSet();”。 ?
 一定有更好的办法吗?能给我指出一个好的方向吗?

最佳答案

我会放弃将辅助Set保留在实例字段中,而是将其实现为静态Map:

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.EnumMap;
import java.util.EnumSet;

public enum StyleEnum {
    NONE(0, "none"),
    BOLD(100, "B"),
    ITALIC(250, "i"),
    UNDERLINE(350, "u"),
    STRIKETHROUGH(9, "b"),
    B_AND_I(99,"Emphase");

    private static Map<StyleEnum, Set<StyleEnum>> complexSubsets;

    private final int intProp;
    private final String strLabel;

    StyleEnum(int intProp, String strLabel) {
        this.intProp = intProp;
        this.strLabel = strLabel;
    }

    public Set<StyleEnum> getComplexSubset() {
        initSubsets();
        return complexSubsets.get(this);
    }

    private static void initSubsets() {
        if (complexSubsets == null) {
            Map<StyleEnum, Set<StyleEnum>> map = new EnumMap<>(StyleEnum.class);
            map.put(NONE, Collections.unmodifiableSet(EnumSet.of(
                BOLD, ITALIC)));
            map.put(BOLD, Collections.unmodifiableSet(EnumSet.of(
                UNDERLINE)));
            map.put(ITALIC, Collections.unmodifiableSet(EnumSet.of(
                UNDERLINE)));
            map.put(UNDERLINE, Collections.emptySet());
            map.put(STRIKETHROUGH, Collections.unmodifiableSet(EnumSet.of(
                NONE)));
            map.put(B_AND_I, Collections.unmodifiableSet(EnumSet.of(
                BOLD, ITALIC)));
            complexSubsets = Collections.unmodifiableMap(map);

            assert complexSubsets.keySet().containsAll(
                EnumSet.allOf(StyleEnum.class)) :
                "Not all values have subsets defined";
        }
    }
}

关于java - 最佳初始化由E实例持有的EnumSet <E>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43348398/

10-10 14:54