当前位置: 代码迷 >> java >> Java - 如何通过字符串访问枚举类和枚举对象?
  详细解决方案

Java - 如何通过字符串访问枚举类和枚举对象?

热度:25   发布时间:2023-07-31 13:42:49.0

所以我有一个带有多个枚举的 java 类

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

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

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”

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

编辑了问题以获得更清晰的观点,这两天和周一都是变量。

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

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

输出:

MON

根据您可能有 200 多个枚举的评论进行更新

您可以像这样使用反射:

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

制作一个静态方法,为您检索适当的枚举值:

//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
}

然后就是直接获取枚举的问题:

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

如果您愿意,您可以创建多种方法来过滤这些输入。 更进一步,如果您真的想发疯,您可以传递Predicate<Days> (或任何枚举)并以这种方式过滤:

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

然后:

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

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

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

我也会在这里遵守枚举的约定(所有大写字母和下划线的间距,所以MONDAY )。

最后,如果这不仅仅是一个示例问题,而且您实际上正在使用天数/日历变量等,那么默认 jdk 中已经提供了DayOfWeekMonth枚举。

尝试反射方式;

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));
    }
}
  相关解决方案