关于Java:Java – 如何通过字符串访问Enum类和Enum对象?

Java - How to access Enum Class and Enum objects via strings?

所以我有一个具有多个Enums的Java类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Enumerations {
    public enum Days {
        Monday("MON")
        Tuesday("Tue")

        string value;
        private Days(String value){
            this.value = value
        }
        public string getValue(){
            return this.value;
        }
    }
    public enum Months{
        January("JAN")
        APRIL("APR")

        string value;
        private Months(String value){
            this.value = value
        }
        public string getValue(){
            return this.value;
        }
    }
}

现在我有了另一个类,我想通过一个字符串访问枚举类,因为我不能直接实例化枚举,因为我不知道要使用的枚举,并且从变量字符串访问枚举值(也不知道这一点)。

1
2
3
4
5
6
class EnumParser{
    public static void main(String args[]){
        String enum ="Days";     //Will get this value from external source so its variable(Can be months or days)
        String value ="Monday"   //This is going to variable as well with value unknown.
    }
}

那么,如何使用字符串变量得到输出为"mon"

1
Enumerations.{{Days}}.{{Monday}}.getValue();

为了更清晰地理解问题,两天和星期一都是变量。


您可以使用if-elseswitch语句来确定要使用的枚举,然后使用valueOf()

1
2
3
4
5
6
7
8
9
10
String e ="Days";
String value ="Monday";

if (e.equalsIgnoreCase(Enumerations.Days.class.getSimpleName())) {
    System.out.println(Enumerations.Days.valueOf(value).getValue());
} else if (e.equalsIgnoreCase(Enumerations.Months.class.getSimpleName())) {
    System.out.println(Enumerations.Months.valueOf(value).getValue());
} else {
    System.out.println("Could not find enum");
}

输出:

1
MON

根据可能有200多个枚举的注释进行更新:

您可以这样使用反射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String e ="Days";
String value ="Monday";

String res = Arrays.stream(Enumerations.class.getDeclaredClasses())
        .filter(c -> c.getSimpleName().equalsIgnoreCase(e))
        .findFirst()
        .map(c -> {
            String result = null;
            try {
                Object o = c.getMethod("valueOf", String.class).invoke(null, value);
                result = (String) o.getClass().getMethod("getValue").invoke(o);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e1) {
                e1.printStackTrace();
            }
            return result;
        }).orElse("Could not find");
System.out.println(res); //prints MON


尝试反思的方式;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.company;

import java.lang.reflect.Method;

class Enumerations {
    public enum Days {
        Monday("MON"),
        Tuesday("Tue");

        String value;
        Days(String value){
            this.value = value;
        }
        public String getValue(){
            return this.value;
        }
    }
    public enum Months{
        January("JAN"),
        APRIL("APR");

        String value;
        Months(String value){
            this.value = value;
        }
        public String getValue(){
            return this.value;
        }
        }
}
public class Main {

    public static void main(String[] args) throws Exception {
        // know the specific class name
        System.out.println(Enumerations.Months.class);
        String enumName ="Days";
        String value ="Monday";
        // get the class by class name
        Class c = Class.forName("com.company.Enumerations$" + enumName);
        // new the object by value
        Object o = Enum.valueOf(c, value);
        // get the method by name
        Method method = c.getMethod("getValue");
        // invoke the method
        System.out.println(method.invoke(o));
    }
}


生成一个静态方法,该方法为您检索适当的枚举值:

1
2
3
4
5
6
7
8
9
//inside Days, skips some excess array creation
private static final Days[] VALUES = Days.values();

public static Days getDay(String day) {
    return Arrays.stream(VALUES)
        .filter(d -> d.value.equalsIgnoreCase(day))
        .findAny(); //Optional<Days>
        //can use #orElse/#orElseThrow to decide behavior for a mismatch
}

然后,只需直接获取枚举即可:

1
Days monday = Days.getDay("MON");

如果您愿意,您可以使用多种方法来过滤这些输入。更进一步,如果你真的想发疯,你可以通过一个Predicate(或任何枚举)并过滤:

1
2
3
4
5
6
public static Days getDay(Predicate<Days> filter) {
    return Arrays.stream(VALUES)
        .filter(filter)
        //In this case I'm returning null for no match
        .findAny().orElse(null);
}

然后:

1
Days monday = Days.getDay(d -> d.getValue().equalsIgnoreCase("MON"));

现在,在严格使用Monday的情况下,可以使用Days#valueOf,但如果搜索的字符串没有枚举常量,则会引发错误。

1
2
3
4
5
Days monday = Days.valueOf("Monday"); //okay
//all of these below would throw an error
monday = Days.valueOf("monday");
monday = Days.valueOf("MONDAY");
monday = Days.valueOf("not even close to monday");

我也会遵守这里的Enum惯例(所有大写字母和下划线都表示间距,所以Monday)。

最后,如果这不仅仅是一个示例问题,而且您实际使用的是天/日历变量等,那么缺省JDK中已经有了DayOfWeekMonth枚举。