Как получить значение перечисления из строкового значения в Java? - PullRequest
1812 голосов
/ 03 марта 2009

Скажем, у меня есть перечисление, которое просто

public enum Blah {
    A, B, C, D
}

и я хотел бы найти значение перечисления строки, например "A", которое будет Blah.A. Как можно было бы сделать это?

Является ли Enum.valueOf() метод, который мне нужен? Если так, как бы я использовал это?

Ответы [ 25 ]

2081 голосов
/ 03 марта 2009

Да, Blah.valueOf("A") даст вам Blah.A.

Обратите внимание, что имя должно быть точным совпадением, включая регистр: Blah.valueOf("a") и Blah.valueOf("A ") оба дают IllegalArgumentException.

Статические методы valueOf() и values() создаются во время компиляции и не отображаются в исходном коде. Они действительно появляются в Javadoc, хотя; например, Dialog.ModalityType показывает оба метода.

795 голосов
/ 03 июня 2010

Другое решение, если текст не совпадает со значением перечисления:

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Blah fromString(String text) {
        for (Blah b : Blah.values()) {
            if (b.text.equalsIgnoreCase(text)) {
                return b;
            }
        }
        return null;
    }
}
111 голосов
/ 12 ноября 2009

Вот изящная утилита, которую я использую:

/**
 * A common method for all enums since they can't have another base class
 * @param <T> Enum type
 * @param c enum type. All enums must be all caps.
 * @param string case insensitive
 * @return corresponding enum, or null
 */
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
    if( c != null && string != null ) {
        try {
            return Enum.valueOf(c, string.trim().toUpperCase());
        } catch(IllegalArgumentException ex) {
        }
    }
    return null;
}

Тогда в моем классе enum я обычно сохраняю набор текста:

public static MyEnum fromString(String name) {
    return getEnumFromString(MyEnum.class, name);
}

Если ваши перечисления не все заглавные, просто измените строку Enum.valueOf.

Жаль, что я не могу использовать T.class для Enum.valueOf, поскольку T стерто.

72 голосов
/ 09 мая 2009

Вы также должны быть осторожны с вашим делом. Позвольте мне объяснить: выполнение Blah.valueOf("A") работает, но Blah.valueOf("a") не будет работать. Тогда снова Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) будет работать.

редактировать
Изменено toUpperCase на toUpperCase(Locale.ENGLISH) на основе tc. комментарий и документы Java

edit2 На Android вы должны использовать Locale.US, а sulai указывает .

66 голосов
/ 15 июня 2016

Используйте шаблон от Джошуа Блоха, Эффективная Java :

(упрощено для краткости)

enum MyEnum {
    ENUM_1("A"),
    ENUM_2("B");

    private String name;

    private static final Map<String,MyEnum> ENUM_MAP;

    MyEnum (String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    // Build an immutable map of String name to enum pairs.
    // Any Map impl can be used.

    static {
        Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
        for (MyEnum instance : MyEnum.values()) {
            map.put(instance.getName(),instance);
        }
        ENUM_MAP = Collections.unmodifiableMap(map);
    }

    public static MyEnum get (String name) {
        return ENUM_MAP.get(name);
    }
}

Также см .:

Пример Oracle Java с использованием Enum и Map of instance

Порядок выполнения статических блоков в типе Enum

Как найти перечисление Java по его строковому значению

36 голосов
/ 02 декабря 2011

Вот метод, который может сделать это для любого Enum и нечувствителен к регистру.

/** 
 * Finds the value of the given enumeration by name, case-insensitive. 
 * Throws an IllegalArgumentException if no match is found.  
 **/
public static <T extends Enum<T>> T valueOfIgnoreCase(
        Class<T> enumeration, String name) {

    for (T enumValue : enumeration.getEnumConstants()) {
        if (enumValue.name().equalsIgnoreCase(name)) {
            return enumValue;
        }
    }

    throw new IllegalArgumentException(String.format(
        "There is no value with name '%s' in Enum %s",
        name, enumeration.getName()
    ));
}
31 голосов
/ 09 мая 2009

Лучше использовать Blah.valueOf(string), но вы также можете использовать Enum.valueOf(Blah.class, string).

26 голосов
/ 03 апреля 2014

Если вы не хотите писать свою собственную утилиту, используйте библиотеку Google :

Enums.getIfPresent(Blah.class, "A")

В отличие от встроенной функции Java, она позволяет вам проверять, присутствует ли А в Blah и не выдает исключение.

22 голосов
/ 13 июля 2017

Мои 2 цента здесь: использование потоков Java8 + проверка точной строки:

public enum MyEnum {
    VALUE_1("Super"),
    VALUE_2("Rainbow"),
    VALUE_3("Dash"),
    VALUE_3("Rocks");

    private final String value;

    MyEnum(String value) {
        this.value = value;
    }

    /**
     * @return the Enum representation for the given string.
     * @throws IllegalArgumentException if unknown string.
     */
    public static MyEnum fromString(String s) throws IllegalArgumentException {
        return Arrays.stream(MyEnum.values())
                .filter(v -> v.value.equals(s))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
    }
}

** РЕДАКТИРОВАТЬ **

Переименовал функцию в fromString(), так как присвоив ей имя, используя это соглашение, вы получите некоторые преимущества от самого языка Java; например:

  1. Прямое преобразование типов в аннотации HeaderParam
19 голосов
/ 01 августа 2017

В Java 8 или более поздней версии, используя Streams :

public enum Blah
{
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Optional<Blah> fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...