Как получить значение перечисления из строкового значения в Java?

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

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

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

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

2.03.2009 22:56:34
27 ОТВЕТОВ
РЕШЕНИЕ

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

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

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

2245
9.09.2017 22:26:47
Для справки, Blah.valueOf("A")метод чувствителен к регистру и не допускает посторонних пробелов, поэтому альтернативное решение, предложенное ниже @ JoséMi.
Brett 17.12.2013 17:37:05
@ Майкл Майерс, так как этот ответ является наиболее голосуемым на сегодняшний день, должен ли я понять, что это хорошая практика, чтобы определять enum и его значение String, чтобы они были точно такими же?
Kevin Meredith 12.02.2014 21:24:44
@KevinMeredith: Если вы имеете в виду toString()значение, нет, я бы так не сказал. name()получит фактическое имя константы enum, если вы не переопределите его.
Michael Myers♦ 14.02.2014 04:10:45
Что именно вы подразумеваете под «создаются во время компиляции и не появляются в исходном коде». ?
treesAreEverywhere 7.03.2014 00:43:08
@treesAreEverywhere Более конкретно, эти методы генерируются (или синтезируются ) компилятором. Фактическое enum Blah {...}определение не должно пытаться объявить свое собственное, valuesни valuesOf. Это похоже на то, как вы можете написать AnyTypeName.class, даже если вы никогда не объявляли переменную-член класса; компилятор делает все это просто работа. (Этот ответ может больше не быть полезным для вас через 3 месяца, но на всякий случай.)
Ti Strga 30.05.2014 19:31:19

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

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

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

74
23.05.2017 12:26:38
Будьте осторожны с локалью по умолчанию!
tc. 28.11.2012 15:43:24
Для вас, пользователей Android, я хотел бы отметить, что документация по Android явно поощряет использование Locale.USдля машиночитаемого ввода / вывода.
sulai 2.09.2013 17:44:51
@ Тренго Да, к сожалению. Турция является хорошим примером. Объедините это с неработающей обработкой Java наборов символов по умолчанию (по умолчанию используется латинский в Windows вместо Unicode), и вы обнаружите, что почти всегда небезопасно использовать версии методов по умолчанию, которые принимают набор символов или локаль. Вы должны почти всегда явно определять их.
Stijn de Witt 26.07.2015 13:34:22
Не уверен, что наборы символов по умолчанию в Java и др. «Сломаны» сами по себе, но предоставлены, по умолчанию вместо UTF-8 вместо переопределений (которые должны быть сделаны всегда, чтобы быть явными) сделали бы лучшие системы для начинающих программистов, которые обычно не понимают концепции кодировки.
Darrell Teague 29.05.2018 20:45:59

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

35
12.08.2013 01:13:19
Чувствителен к регистру, не помогает!
Murtaza Kanchwala 28.06.2015 18:58:12
@MurtazaKanchwala Можете ли вы уточнить свой комментарий? Что ты пытаешься сделать?
Peter Lawrey 29.06.2015 10:18:25
Привет @PeterLawrey, я пытался получить Enum из открытого перечисления String ObjectType {PERSON ("Person") public String parameterName; ObjectType (String параметрName) {this.parameterName = параметрName; } public String getParameterName () {return this.parameterName; } public static ObjectType fromString (String parameterName) {if (parameterName! = null) {for (ObjectType objType: ObjectType.values ​​()) {if (parameterName.equalsIgnoreCase (objType.parameterName)) {return objType; }}} return null; }}
Murtaza Kanchwala 29.06.2015 17:45:51

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

/**
 * 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стирается.

121
17.11.2014 20:23:38
Этот пустой блок улова действительно сводит меня с ума, извините.
whiskeysierra 31.07.2010 10:14:55
@LazloBonin: Исключения для исключительных условий, а не для потока управления. Получите себе копию Effective Java .
Reinstate Monica - M. Schröder 15.11.2011 17:09:06
Если Java API, который вы хотите использовать, генерирует исключение, и вы не хотите, чтобы ваш код генерировал его, вы можете либо проглотить исключение, как это, либо переписать логику с нуля, чтобы исключение не создавалось в первую очередь. Глотание исключения часто является меньшим злом.
Nate C-K 30.11.2011 19:26:55
Ужасный! Всегда, всегда ловите исключения, где вы можете их обработать. Приведенный выше пример является прекрасным примером того, как НЕ делать этого . Почему? Таким образом, он возвращает NULL, и тогда вызывающий должен проверить NULL или бросить NPE. Если вызывающий знает, как справиться с ситуацией, тогда выполнение if vs. try-catch может выглядеть немного более элегантно, НО, если он не может обработать, он должен снова передать значение null, а вызывающий объект снова должен проверить на NULL. и т. д. и т. д.
raudi 2.02.2012 07:52:31
Чтобы быть справедливым по отношению к решению, приведенному выше, существуют действительно случаи, требующие, чтобы вы возвращали null вместо того, чтобы выдавать IllegalArgumentException и прерывать поток вашей программы, например, отображая перечисления между схемой веб-службы и схемой базы данных, где они не всегда едины. -к одному. Однако я согласен с тем, что блок catch никогда не следует оставлять пустым. Поместите некоторый код как log.warn или что-то для отслеживания цели
Adrian M 6.02.2012 08:19:39

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

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;
    }
}
856
8.02.2019 14:15:45
throw new IllegalArgumentException("No constant with text " + text + " found")было бы лучше, чем return null.
whiskeysierra 31.07.2010 10:28:46
@ whiskeysierra Джон Скит не согласится с этим. stackoverflow.com/questions/1167982/…
Sanghyun Lee 5.09.2011 04:06:16
@Sangdol Не могли бы вы рассказать нам, почему возвращать ноль лучше?
whiskeysierra 29.09.2011 15:04:35
@Sangdol обычно полезно проверить, что SUN - упс - Oracle делает в такой же ситуации. И как Enum.valueOf () показывает , что IS лучшая практика бросить исключение в этом случае. Потому что это исключительная ситуация. «Оптимизация производительности» - плохое предлог для написания нечитаемого кода ;-)
raudi 2.02.2012 07:43:58
Ну, вы также можете использовать аннотацию @Nullable, чтобы сделать ее «читабельной» ;-)
JoséMi 3.02.2012 08:20:37
public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}
6
22.04.2015 21:50:50
Посмотрите эту ссылку, чтобы
bakoyaro 9.11.2011 18:15:06
Это более или менее такое же , как ответ Хосого в
Rup 14.11.2011 12:40:14

Еще один способ сделать это с помощью неявного статического метода name()Enum. name возвращает точную строку, использованную для создания этого перечисления, которое можно использовать для проверки по предоставленной строке

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

Тестирование:

System.out.println(Blah.getEnum("B").name());

//it will print B  B

вдохновение: 10 примеров Enum на Java

13
29.11.2011 05:48:52
По сути, это то, valueOfчто вам нужно. Этот статический метод не предлагает ничего лишнего, исключение и все такое. Тогда конструкции if / else очень опасны ... любая добавленная новая константа перечисления вызовет разрыв этого метода без изменений.
YoYo 30.09.2012 18:01:39
Рассмотрим также этот пример того, как мы можем использовать valueOf для поиска без учета регистра или как мы можем избежать его исключения и использовать псевдонимы для предоставления альтернативных имен: stackoverflow.com/a/12659023/744133
YoYo 30.09.2012 18:18:33
name()не является статичным
nrubin29 21.04.2014 00:39:07

Вот метод, который может сделать это для любого 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()
    ));
}
38
22.04.2015 21:22:37
Этот вариант делает это правильно: equalsIgnoreCaseэто путь. +1
Stijn de Witt 26.07.2015 13:35:57
Подобно нечувствительности к регистру, но ... предпочитают Enums вместо (случайных) строковых назначений для ключей и ... второстепенных, но итерация менее производительна для такого возможно повторного поиска. Отсюда вытекает из EnumMap et al.
Darrell Teague 13.08.2018 17:26:57
Это не работает ! Я изменил equalsIgnoreCase на equals для моей цели. Код не удался, хотя оба входа равны были точно одинаковыми.
MasterJoe2 26.11.2018 20:49:08

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

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

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

28
2.04.2014 20:12:18
грустная часть, это возвращает Google Необязательный, а не Java Необязательный
javaProgrammer 19.08.2016 00:02:58
Правда. Тем не менее У Google и Netflix есть отличные библиотеки Java. Там, где есть пересечение с классами догоняющего Java, реализованными в более новых версиях, неизбежно возникают проблемы. Вид должен быть олл-ин на одного поставщика lib.
Darrell Teague 13.08.2018 17:30:08

Решение с использованием библиотек Guava. Метод getPlanet () нечувствителен к регистру, поэтому getPlanet ("MerCUrY") вернет Planet.MERCURY.

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}
10
23.08.2014 02:02:09

Чтобы добавить к предыдущим ответам и обсудить некоторые дискуссии вокруг нулей и NPE, я использую дополнительные возможности Guava для обработки отсутствующих / недействительных случаев. Это прекрасно работает для разбора URI / параметров.

public enum E {
    A,B,C;
    public static Optional<E> fromString(String s) {
        try {
            return Optional.of(E.valueOf(s.toUpperCase()));
        } catch (IllegalArgumentException|NullPointerException e) {
            return Optional.absent();
        }
    }
}

Для тех, кто не знает, вот еще некоторая информация о том, как избежать нуля с помощью Необязательно: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

8
22.04.2015 21:56:49
Это действительно хороший ответ для связанных шаблонов и использования Optional внутри Enum - используя тот факт, что Enums тоже являются классами и, следовательно, могут быть украшены методами, методами переопределения и т. Д. Это хороший случай для программирования в стиле Fluent, так как нули, возвращаемые из методов, делают эту конструкцию ошибочной (NPE в неизвестных местах в цепочках вызовов методов Fluent).
Darrell Teague 15.04.2020 22:09:41

java.lang.Enum определяет несколько полезных методов, которые доступны для всех типов перечисления в Java:

  • Вы можете использовать name()метод, чтобы получить имя любой константы Enum. Строковый литерал, используемый для записи констант enum, является их именем.
  • Аналогичным образом values()метод можно использовать для получения массива всех констант Enum из типа Enum.
  • А для заданного вопроса вы можете использовать valueOf()метод для преобразования любой String в Enum константу в Java, как показано ниже.
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

В этом фрагменте кода valueOf()метод возвращает константу Enum Gender.MALE, вызывающую имя для возвращаемого значения "MALE".

4
22.04.2015 21:54:41

Вам может понадобиться это:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    //From String method will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

Еще одно дополнение:

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

Это вернет вам значение по строковому имени Enum. Например, если вы укажете «PERSON» в fromEnumName, он вернет вам значение Enum, то есть «Person»

16
29.10.2015 14:38:55

O (1) метод, основанный на экономически сгенерированном коде, который использует хэш-карту.

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}
6
23.09.2015 09:08:33
Обратите внимание, что нулевой (0) и один (1) идентификаторы не нужны. Метод Enum values ​​() возвращает элементы в том же порядке, что и кодированный. Таким образом, первая запись будет иметь порядковый ноль, вторая и т. Д.
Darrell Teague 15.04.2020 22:13:45

Библиотека Apache commons-lang имеет статическую функцию org.apache.commons.lang3.EnumUtils.getEnum, которая сопоставит строку с вашим типом Enum. Тот же ответ, что и у Джеффриса, но зачем бросать свой, когда он уже в дикой природе.

4
22.10.2015 06:46:11
Честный комментарий (СУХОЙ), но ... хотя большинство вещей Apache Commons великолепны, я обнаружил в этой базе несколько ошибок и анти-паттернов. Таким образом, говоря о том, что реализация Джошуа Блоха может быть более сильной. Затем приходится пересматривать код Apache, чтобы узнать, что кто-то реализовал. Если бы это был, скажем, знаменитый Даг Ли, который переписал параллелизм Java ... тогда я бы доверял этому безоговорочно.
Darrell Teague 15.04.2020 22:16:00

Еще одна утилита захвата в обратном порядке. Использование значения, которое идентифицирует этот Enum, а не по его имени.

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;

public class EnumUtil {

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
     * public method return value of this Enum is 
     * equal to <code>valor</code>.<br/>
     * Such method should be unique public, not final and static method 
     * declared in Enum.
     * In case of more than one method in match those conditions
     * its first one will be chosen.
     * 
     * @param enumType
     * @param value
     * @return 
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
        String methodName = getMethodIdentifier(enumType);
        return from(enumType, value, methodName);
    }

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose  
     * public method <code>methodName</code> return is 
     * equal to <code>value</code>.<br/>
     *
     * @param enumType
     * @param value
     * @param methodName
     * @return
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
        EnumSet<E> enumSet = EnumSet.allOf(enumType);
        for (E en : enumSet) {
            try {
                String invoke = enumType.getMethod(methodName).invoke(en).toString();
                if (invoke.equals(value.toString())) {
                    return en;
                }
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    private static String getMethodIdentifier(Class<?> enumType) {
        Method[] methods = enumType.getDeclaredMethods();
        String name = null;
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
                name = method.getName();
                break;
            }
        }
        return name;
    }
}

Пример:

public enum Foo {
    ONE("eins"), TWO("zwei"), THREE("drei");

    private String value;

    private Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

EnumUtil.from(Foo.class, "drei")возвращается Foo.THREE, потому что он будет использовать getValueдля сопоставления «drei», который является уникальным public, не final и не статическим методом в Foo. В случае , если Foo имеет более чем на общественном, а не окончательным и не статический метод, например, getTranslateкоторый возвращает «драй», другой метод может быть использован: EnumUtil.from(Foo.class, "drei", "getTranslate").

1
24.02.2016 11:39:28

Используйте образец из Джошуа Блоха, Эффективная 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 по его строковому значению

100
8.02.2019 14:17:31
если Джошуа Блох сказал это, то это единственный путь :-). Это позор, что я всегда должен прокручивать здесь.
dermoritz 10.01.2017 09:51:41
Это даже проще в Java 8, чем вы можете сделать: Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))я также рекомендую переопределить toString () (переданный через конструктор) и использовать его вместо имени, особенно если Enum связан с сериализуемыми данными, так как это позволяет вам управлять регистром без предоставления Сонар подходит.
Novaterata 27.04.2017 17:01:13
Java 8, безусловно, может / изменит многие (лучшие) ответы на этом форуме. Не уверен в том, что когда-либо хвастался (Сонар) вилять собакой (код приложения).
Darrell Teague 28.04.2017 20:31:57
Если вы все unmodifiableMapравно собираетесь это вставить , то начинать с a не имеет смысла ConcurrentHashMap. Просто используйте HashMap. (Если у вас есть гуава, ImmutableMapто я бы порекомендовал это вместо этого!)
Daniel Pryden 8.03.2018 16:13:53
Статическая инициализация изначально синхронизирована , поэтому нет абсолютно никакой причины использовать ее ConcurrentHashMapздесь, где карта никогда не изменяется после инициализации. Следовательно, почему даже, например, пример в самом JLS использует регулярный HashMap.
Radiodef 5.08.2018 17:24:28

Мне нравится использовать этот процесс для анализа команд в виде строк в перечислениях. У меня обычно одно из перечислений как «неизвестное», поэтому полезно возвращать его, когда другие не найдены (даже без учета регистра), а не ноль (это означает, что значения нет). Поэтому я использую этот подход.

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
    Enum<E> unknown=null;
    for (Enum<E> enumVal: enumClass.getEnumConstants()) {  
        if (what.compareToIgnoreCase(enumVal.name()) == 0) {
            return enumVal;
        }
        if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
            unknown=enumVal;
        }
    }  
    return unknown;
}
0
30.08.2016 09:11:58

Добавление к ответу с самым высоким рейтингом, с полезной утилитой ...

valueOf() выдает два разных исключения в тех случаях, когда ему не нравится его ввод.

  • IllegalArgumentException
  • NullPointerExeption

Если ваши требования таковы, что у вас нет никаких гарантий, что ваша строка будет точно соответствовать значению перечисления, например, если данные строки поступают из базы данных и могут содержать старую версию перечисления, то вам нужно будет обработать эти довольно часто...

Итак, вот метод многократного использования, который я написал, который позволяет нам определить Enum по умолчанию, который будет возвращен, если передаваемая строка не совпадает.

private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
        try {
            return Enum.valueOf(defaultVal.getDeclaringClass() , name);
        } catch (IllegalArgumentException | NullPointerException e) {
            return defaultVal;
        }
    }

Используйте это так:

public enum MYTHINGS {
    THINGONE,
    THINGTWO
}

public static void main(String [] asd) {
  valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
  valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}
4
11.07.2017 17:01:56

В Java 8 шаблон статической карты еще проще и является моим предпочтительным методом. Если вы хотите использовать Enum с Джексоном, вы можете переопределить toString и использовать его вместо имени, затем аннотировать@JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

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

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}
8
27.04.2017 17:10:02
Джексон - это реализация JSON (JavaScript Object Notation). Первоначальный вопрос не имел ничего общего с JSON.
Darrell Teague 15.04.2020 22:06:44
Часть JSON была просто бонусным материалом, который мне показался актуальным в то время, поскольку получение Enum из строки - это, по сути, тип десериализации, а JSON / Jackson, вероятно, является наиболее популярным решением для сериализации.
Novaterata 16.04.2020 01:38:23
Поймите, но с точки зрения модерации - это не способствовало ответу на вопрос OP, поэтому просто попытка помочь установить контекст там. JSON - действительно способ преобразования объектов в каноническую форму в Java с Джексоном, являющимся отличной библиотекой.
Darrell Teague 17.04.2020 12:50:10

Мои 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
25
9.01.2019 09:59:17
В качестве альтернативы, чтобы вы могли писать более читаемые switchблоки, вы можете .orElse(null)вместо .orElseThrow()этого кодировать исключение, выбрасываемое в defaultпредложении, и включать больше полезной информации, когда это необходимо. И чтобы сделать его более снисходительным, вы можете использоватьv -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Adam 10.05.2018 11:35:00
или просто вернуть Optionalиз findFirst(), что позволяет пользователю решить , хочет ли он .orElse(null), orElseThrow()или что - то ....
user85421-Banned 2.08.2018 20:58:50
Объявление a public static MyEnum valueOf(String)на самом деле является ошибкой компиляции, поскольку оно совпадает с неявно определенным, поэтому старая версия вашего ответа на самом деле лучше. ( JLS , ideone )
Radiodef 23.12.2018 23:34:13
В моем варианте лучше избегать исключений и использовать опционально. Кроме того, мы должны аннулировать null и использовать Optional.
Hans Schreuder 23.05.2019 10:57:55
Опять же, просто помните, что даже если код выглядит лучше или хуже ... реализация Stream, подобная этой, является просто итератором для всех значений по сравнению с поиском на карте (менее производительным).
Darrell Teague 15.04.2020 22:05:08

В 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();
    }
}
34
26.04.2019 11:47:47
Не уверен, что это как-то лучше ответ. Потоки в этом случае являются однопоточными итераторами, как и любые другие по всем значениям, и, возможно, менее производительными, чем подразумеваемый просмотр карты. Потоки имеют большую ценность в многопоточном контексте, где, например, параллельное выполнение разделенного новой строкой текстового файла может улучшить производительность.
Darrell Teague 15.04.2020 22:03:48

Что о?

public enum MyEnum {
    FIRST,
    SECOND,
    THIRD;

    public static Optional<MyEnum> fromString(String value){
        try{
            return Optional.of(MyEnum.valueOf(value));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}
4
30.12.2017 07:38:31

Поскольку switch-версия еще не упоминалась, я представляю ее (повторно используя перечисление OP):

  private enum Blah {
    A, B, C, D;

    public static Blah byName(String name) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          throw new IllegalArgumentException(
            "No enum constant " + Blah.class.getCanonicalName() + "." + name);
      }
    }
  }

Поскольку это не дает никакой дополнительной ценности valueOf(String name)методу, имеет смысл определять дополнительный метод, только если мы хотим иметь другое поведение. Если мы не хотим поднимать, IllegalArgumentExceptionмы можем изменить реализацию на:

  private enum Blah {
    A, B, C, D;

    public static Blah valueOfOrDefault(String name, Blah defaultValue) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          if (defaultValue == null) {
            throw new NullPointerException();
          }
          return defaultValue;
      }
    }
  }

Предоставляя значение по умолчанию , мы соблюдаем контракт о Enum.valueOf(String name)не бросать IllegalArgumentException в такой манере , что ни в коем случае nullне возвращается. Поэтому мы бросаем, NullPointerExceptionесли имя nullи в случае, defaultесли defaultValueесть null. Вот как это valueOfOrDefaultработает.

Этот подход принимает дизайн Map-Interface, который обеспечивает метод Map.getOrDefault(Object key, V defaultValue)с Java 8.

2
2.08.2018 21:19:58

Самый быстрый способ получить имя enum - это создать карту текста и значения enum при запуске приложения и получить имя, вызвав функцию Blah.getEnumName ():

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

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

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

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.name());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}
-1
31.03.2020 06:11:37

Enum очень полезен, я много использовал Enumдля добавления описания некоторых полей на разных языках, как в следующем примере:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

И затем вы можете получить описание динамически на основе кода языка, переданного getDescription(String lang)методу, например:

String statusDescription = Status.valueOf("ACT").getDescription("en");
6
23.06.2019 08:44:06
Хороший пример с продвижением Enums дальше. Сделал бы языковую кодировку, используя стандартные статические имена и поиск в Map, но все же ... хороший пример наличия перечисления с разными тегами для того, что по сути является одним и тем же логическим значением.
Darrell Teague 15.04.2020 22:11:57

Kotlin Solution

Создайте расширение, а затем позвоните valueOf<MyEnum>("value"). Если тип недействителен, вы получите ноль и должны обработать его

inline fun <reified T : Enum<T>> valueOf(type: String): T? {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        null
    }
}

Кроме того, вы можете установить значение по умолчанию, вызывая valueOf<MyEnum>("value", MyEnum.FALLBACK)и избегая нулевого ответа. Вы можете расширить свой конкретный enum, чтобы по умолчанию он был автоматическим

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        default
    }
}

Или, если вы хотите оба, сделайте второе:

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
1
18.01.2020 00:08:41