简体   繁体   English

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

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

So I have a java class with multiple Enums所以我有一个带有多个枚举的 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;
        }
    }
}

And now I have another class in which I want to access the enum class via a string as i cannot instantiate the enum directly as i am unaware of the enum that is to be used and access enum values from a variable string(unaware of this as well).现在我有另一个类,我想通过字符串访问枚举类,因为我无法直接实例化枚举,因为我不知道要使用的枚举并从变量字符串访问枚举值(不知道这是因为好)。

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

So how do i get output as "MON" here using string variables那么我如何在这里使用字符串变量将输出作为“MON”

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

edited the question for a clearer view, both Days ans Monday are variables.编辑了问题以获得更清晰的观点,这两天和周一都是变量。

You can use if-else or switch statements to determine which enum to use, and then use valueOf() :您可以使用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");
}

Output:输出:

MON

Update based on comment that you might have 200+ enums:根据您可能有 200 多个枚举的评论进行更新

You can use reflection like so:您可以像这样使用反射:

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

Make a static method which retrieves the appropriate enum value for you:制作一个静态方法,为您检索适当的枚举值:

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

Then it's a matter of simply getting the enum directly:然后就是直接获取枚举的问题:

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

You can make multiple methods which filter around these inputs, if you like.如果您愿意,您可以创建多种方法来过滤这些输入。 Even further if you really want to get crazy, you can pass a Predicate<Days> (or whichever enum) and filter that way:更进一步,如果您真的想发疯,您可以传递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);
}

Then:然后:

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

Now in the strict case of Monday , you can use Days#valueOf , but this will throw an error if there is no enum constant for the string you search for.现在在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");

I would also adhere to conventions for enums here (all caps letters and underscores for spacing, so MONDAY ).我也会在这里遵守枚举的约定(所有大写字母和下划线的间距,所以MONDAY )。

Lastly, if this isn't just an example problem and you're actually working with days/calendar variables etc, you have the DayOfWeek and Month enums already available in the default jdk.最后,如果这不仅仅是一个示例问题,而且您实际上正在使用天数/日历变量等,那么默认 jdk 中已经提供了DayOfWeekMonth枚举。

Try reflection way;尝试反射方式;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM