我在Groovy中定义了以下枚举,但是出于这个问题的目的,它可能是Java代码:
enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static Set<String> allSearchTokens = new HashSet<String>();
FestivalType() {
String searchToken = this.name().tokenize('_').first().toLowerCase();
if (searchToken in allSearchTokens) {
throw new RuntimeException("Duplicate search token");
} else {
this.searchToken = searchToken;
allSearchTokens.add(searchToken);
}
}
final String searchToken;
}
我在构造函数中尝试做的是确定每个枚举常量名称中的第一个标记是否唯一,其中_
用作标记分隔符。
但是,此代码不起作用,因为allSearchTokens
在实例化所有常量之后才初始化,所以我在这里得到NullPointerException
allSearchTokens.add(searchToken)
答案 0 :(得分:4)
您可以按照以下方式解决此问题:
public enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static class SetHolder {
static Set<String> allSearchTokens = new HashSet<String>();
}
final String searchToken;
FestivalType() {
String searchToken = name().split("_")[0].toLowerCase();
if (SetHolder.allSearchTokens.contains(searchToken))
throw new RuntimeException("Duplicate search token");
this.searchToken = searchToken;
SetHolder.allSearchTokens.add(searchToken);
}
}
由于java规范的编译,所有静态初始值设定项必须在使用类之前完成。通过将Set设置为sttic内部类的静态字段,可以保证在构造第一个枚举之前对其进行初始化。
此外,我冒昧地在您的代码中更改/修复了一些内容:
Set
而不是List
:值是唯一的split()
:java中的tokenize()
没有此类方法String
else
:在return
或throws
之后,else
始终是多余的,因为这些关键字会暂停执行该块(没有“其他”到处理)
顺便说一句,这项技术对于lazy initialization的singletons来说也很棒:
public class MyLazySingleton() {
private static class InstanceHolder {
static MyLazySingleton INSTANCE = new MyLazySingleton();
}
public static MyLazySingleton getInstance() {
return InstanceHolder.INSTANCE;
}
}
INSTANCE
字段仅在首次调用getInstance()
方法时构建!
看妈妈!没有锁的懒惰初始化,没有空检查,没有任何类型的同步和 100%防弹! (尽管对象反序列化仍然存在)
这很神奇:)
答案 1 :(得分:1)
我做了类似的事情,以下内容对我有用:
enum MyEnum{
Enum1, Enum2;
private static List<String> myList;
private static void addToList(MyEnum enum){
if(myList == null){
myList = new ArrayList<String>();
}
myList.add(enum.name());
}
private MyEnum(){
addToList(this);
}
}