Как получить доступ к объектам Enum Class и Enum через строки? - PullRequest
0 голосов
/ 14 февраля 2019

Итак, у меня есть класс 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();

отредактировал вопрос для более ясного представления, оба дня и понедельник являются переменными.

Ответы [ 3 ]

0 голосов
/ 14 февраля 2019

Создайте статический метод, который извлекает подходящее для вас значение перечисления:

//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).

Наконец, если это не просто примерная проблема, и вы фактически работаете с переменными дня / календаря и т. д., у вас есть *Перечисления 1022 * и Month уже доступны в jdk по умолчанию.

0 голосов
/ 14 февраля 2019

Попробуйте способ отражения;

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));
    }
}
0 голосов
/ 14 февраля 2019

Вы можете использовать операторы if-else или switch, чтобы определить, какое перечисление использовать, а затем использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...