2012-02-03 49 views
4

我定义在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) 

回答

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():没有这样的方法tokenize()对于String in java
  • 删除else:在returnthrows之后,else始终是冗余的,因为块的执行被这些关键字阻止(没有“e伦敦政治经济学院”来处理)


顺便说一句,这种技术也非常适合lazy initializationsingletons的:

public class MyLazySingleton() { 
    private static class InstanceHolder { 
     static MyLazySingleton INSTANCE = new MyLazySingleton(); 
    } 

    public static MyLazySingleton getInstance() { 
     return InstanceHolder.INSTANCE; 
    } 
} 

INSTANCE场只有构建在getInstance()方法首先被调用!

看妈妈!没有锁的懒惰初始化,没有空检查,没有任何种类的同步 100%防弹! (尽管有对象反序列化攻击)

It's magic :)

+0

不错!我将在未来使用该机制而不是我的机制。 – 2012-02-03 12:27:12

+1

非常聪明,非常感谢。顺便说一句,'tokenize()'是Groovy添加到String类的一种方法 – 2012-02-03 12:31:07

+0

我想我记得在有效Java的第2版中使用这种技术进行单例构建 - 必读 – 2012-02-03 12:42:09

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


}