簡體   English   中英

最佳初始化EnumSet <E> 以E為例

[英]Best initializing for an EnumSet<E> holded by instance of E

我正在處理一些關於我使用一些不安全(無類型安全)String或部分模型的int表示的地方的工作,並利用Enum和EnumSet最佳實踐。

一個特殊的難點是這個用例:一個枚舉,其中每個實例都擁有自己姐妹的[0..n]的EnumSet。

根據Joshua Bloch關於StyleEnum的問題,我將其簡化為基本要素。 所以我們得到了BOLD,ITALIC,UNDERLINE,STRIKETHROUGH的枚舉......讓我們想象一下B_AND_I將保持{BOLD,ITALIC}。

請不要采用無意義的例子:在真實系統中,這個子集是基於一些加載@啟動時間的變化規則構建的。

目標是一旦發生這種計算,沒有什么可以改變實例特定的子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);
}

Etvoilà!

而不是那樣,我能做的所有事情似乎都在場上拉開決賽

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

然后在類的靜態初始化程序塊循環中實例化(虛擬)標記(NONE)僅為此(愚蠢)目的引入:

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

並且只有在那之后計算並存儲子EnumSet。

所有這些痛苦 - 通常 - 只是因為一個人不能說“新的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";
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM