我正在处理一些关于我使用模型的一部分的不安全(无类型安全)字符串或整数表示的地方的工作。并利用 Enum 和 EnumSet 最佳实践。
一个特别的困难是这个用例:一个 Enum,其中每个实例都拥有一个其自己的姐妹的 [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);
}
等等瞧!
取而代之的是,我所能做的似乎是在场上拉开决赛
// getting away from the final keyword
private EnumSet<StyleEnum> complexComputedSubSet;
然后在类的静态初始化程序块循环中并使用仅为此(愚蠢)目的引入的(虚拟)标记(NONE)进行实例化:
for (StyleEnum e : EnumSet.allOf(StyleEnum.class)) {
e.complexComputedSubSet = EnumSet.of(NONE);
}
并且只有在计算和存储子 EnumSet 之后。
所以所有这些痛苦,主要是因为不能说“new EnumSet();” ? 一定有更好的办法吗?你能给我指出好的方向吗?