2012-04-17 56 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中)不同之处在于它不抛出异常为一个无效的枚举名称。

相关问题