2012-04-17 26 views
10

我有兩個不同的枚舉,我希望能夠輸出給定的 字符串是否是枚舉集合的一部分。這是我的代碼:如何檢查給定的字符串是否是Java中任何給定枚舉的一部分?

public class Check { 
    public enum Filter{SIZE, DATE, NAME}; 
    public enum Action{COPY, DELETE, REMOVE}; 

    public boolean isInEnum(String value, Enum e){ 
     // check if string value is a part of a given enum 
     return false; 
    } 

    public void main(){ 
     String filter = "SIZE"; 
     String action = "DELETE"; 
       // check the strings 
     isInEnum(filter, Filter); 
     isInEnum(action, Action); 
    } 
} 

日食說,在最後兩行「過濾器不能被解析爲一個變量」,但 除了那似乎在功能「isInEnum」枚舉參數是錯誤的。

這裏有什麼是非常錯誤的,任何人都可以幫忙嗎?

+0

你說對了:)枚舉只是一個普通的類,你可以不提它的名字那樣。枚舉是他們枚舉的實例,而不是整個枚舉。 – 2012-04-17 21:31:59

回答

20

最簡單的(通常是最有效的)方法如下:

public <E extends Enum<E>> boolean isInEnum(String value, Class<E> enumClass) { 
    for (E e : enumClass.getEnumConstants()) { 
    if(e.name().equals(value)) { return true; } 
    } 
    return false; 
} 

然後調用isInEnum(filter, Filter.class)

+0

如何'enumClass.getMethod( 「的valueOf」,String.class).invoke(NULL,值)'? – 2012-04-17 21:33:37

+1

這並獲得成功,但語法是瘋了..需要了解這些仿製藥 – Tom 2012-04-17 21:35:49

+1

@MarkoTopolnik有點爲什麼使用反射,當您通過要素反正循環,你可以用'e.valueOf(值)'代替。使用的valueOf時,你必須趕上還要注意'IllegalArgumentException'如果名稱不存在,'NullPointerException'如果字符串爲null – Ozzy 2012-04-17 21:42:53

0

避免使用循環進行驗證。

我建議使用valueOf。此方法內置枚舉,並可能考慮編譯時優化。

這將類似於實現靜態Map<String,EnumType>來優化查找,您可以採取其他考慮。

缺點是您必須使用異常處理機制來捕獲非枚舉值。

public enum DataType { 
    //... 
    static public boolean has(String value) { 
    if (value== null) return false; 
    try { 
     // In this implementation - I want to ignore the case 
     // if you want otherwise ... remove .toUpperCase() 
     return valueOf(value.toUpperCase()); 
    } catch (IllegalArgumentException x) { 
     // the uggly part ... 
     return false; 
    } 
    } 
} 

也要注意,使用上述類型的實現,要求當你的代碼看起來清爽多了。你的主現在看起來像這樣:

public void main(){ 
    String filter = "SIZE"; 
    String action = "DELETE"; 

    // ... 

    if (Filter.has(filter) && Action.has(action)) { 
     // Appropriate action 
    } 
} 

然後另一個提到的選項是使用靜態地圖。您也可以使用這種方法來緩存基於其他屬性的所有類型的索引。在下面的例子中,我允許每個枚舉值都有一個別名列表。在這種情況下查找索引將不區分大小寫,強制轉換爲大寫。

public enum Command { 
    DELETE("del","rm","remove"), 
    COPY("cp"), 
    DIR("ls"); 

    private static final Map<String,Command> ALIAS_MAP = new HashMap<String,Command>(); 
    static { 
    for (Command type:Command.values()) { 
     ALIAS_MAP.put(type.getKey().toUpper(),type); 
     for (String alias:type.aliases) ALIAS_MAP.put(alias.toUpper(),type); 
    } 
    } 

    static public boolean has(String value) { 
    return ALIAS_MAP.containsKey(value.toUpper()); 
    } 

    static public Command fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Command command = ALIAS_MAP.get(value); 
    if (command == null) throw new IllegalArgumentException("Not an alias: "+value); 
    return command; 
    } 

    private List<String> aliases; 
    private Command(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
    } 
} 
+0

請注意有關例外開銷的評論帖子。當我第一次發佈時,他們對我隱藏了。 – YoYo 2012-09-28 19:00:03

+0

我在看另一個類似的話題。一位用戶提到,在這種情況下,JIT編譯器會優化異常開銷。由於所有儀器的調試,開銷只有在調試時才顯着。 – YoYo 2012-09-29 23:35:59

4

這是一個Java 8 /流版本的路易Wasserman的答案。 (您也可以直接把這個方法到枚舉類,並刪除其中的一個參數)

public boolean isInEnum(String value, Class<E> enumClass) { 
    return Arrays.stream(enumClass.getEnumConstants()).anyMatch(e -> e.name().equals(value)); 
    } 
2

我沒有足夠的積分,在西門塔的回答直接發表評論,但這裏是第二個方法他提到的方式,直接進入該枚舉類本身:

public static boolean isInEnum(String value) { 
    return Arrays.stream(EnumClassNameGoesHere.values()).anyMatch(e -> e.name().equals(value)); 
} 
8

如果你不介意使用Apache公地lang3庫中,可以使用下面的代碼:

EnumUtils.isValidEnum(Filter.class, filter) 

根據該docs

此方法從Enum.valueOf(java.lang.Class中,java.lang.String中)不同之處在於它不拋出異常爲一個無效的枚舉名稱。

相關問題