Dis que j'ai un enum qui est juste
public enum Blah {
A, B, C, D
}
et j'aimerais trouver la valeur enum d'une chaîne, par exemple "A"
qui serait Blah.A
. Comment serait-il possible de faire cela?
Est-ce que Enum.valueOf()
est la méthode dont j'ai besoin? Si oui, comment pourrais-je l'utiliser?
Oui, Blah.valueOf("A")
vous donnera _Blah.A
_.
Notez que le nom doit être une correspondance exacte , y compris la casse: Blah.valueOf("a")
et Blah.valueOf("A ")
jettent tous deux une IllegalArgumentException
.
Les méthodes statiques valueOf()
et values()
sont créées à la compilation et n'apparaissent pas dans le code source. Ils apparaissent dans Javadoc, cependant; Par exemple, Dialog.ModalityType
affiche les deux méthodes.
Une autre solution si le texte n’est pas identique à la valeur d’énumération:
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;
}
}
Voici un utilitaire astucieux que j'utilise:
/**
* 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;
}
Ensuite, dans mon cours d’énumération, j’ai l'habitude de garder ceci en mémoire:
public static MyEnum fromString(String name) {
return getEnumFromString(MyEnum.class, name);
}
Si vos enums ne sont pas tous en majuscules, changez simplement la ligne Enum.valueOf
.
Dommage que je ne puisse pas utiliser T.class
pour Enum.valueOf
, car T
est effacé.
Utilisez le modèle de Joshua Bloch, Effective Java :
(simplifié pour la brièveté)
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);
}
}
Regarde aussi:
Oracle Java Exemple utilisant Enum et Map of instances
Ordre d'exécution des blocs statiques dans un type Enum
Comment puis-je rechercher un Java enum à partir de sa valeur String
Vous devriez également faire attention à votre cas. Laissez-moi vous expliquer: faire Blah.valueOf("A")
fonctionne, mais Blah.valueOf("a")
ne fonctionnera pas. Là encore, Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
fonctionnerait.
modifier
Remplacé toUpperCase
par toUpperCase(Locale.ENGLISH)
sur la base de tc. Comment et de la documentation Java
edit2 Sur Android, vous devez utiliser Locale.US
, comme points sulai out .
Voici une méthode qui peut le faire pour tout Enum, sans distinction de casse.
/**
* 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()
));
}
Utiliser Blah.valueOf(string)
est préférable, mais vous pouvez également utiliser Enum.valueOf(Blah.class, string)
.
Si vous ne voulez pas écrire votre propre utilitaire, utilisez la bibliothèque guava de Google:
Enums.getIfPresent(Blah.class, "A")
Contrairement à la fonction Java intégrée, elle vous permet de vérifier si A est présent dans Blah et ne lève pas d'exception.
Dans Java 8 ou version ultérieure, à l'aide de 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();
}
}
Mes 2 centimes ici: utilisation de Java8 Streams + vérification d'une chaîne exacte:
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));
}
}
** MODIFIER **
Vous avez renommé la fonction fromString()
puisque vous l'avez nommée à l'aide de cette convention, vous tirerez parti du langage Java. par exemple:
Vous devrez peut-être ceci:
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;
}
}
Un ajout de plus:
public static String fromEnumName(String parameterName) {
if (parameterName != null) {
for (DQJ objType : DQJ.values()) {
if (parameterName.equalsIgnoreCase(objType.name())) {
return objType.parameterName;
}
}
}
return null;
}
Cela vous retournera la valeur par un nom d'énumération Stringified, par exemple. si vous fournissez "PERSON" dans le nom fromEnumName, la valeur Enum vous sera renvoyée, c'est-à-dire "Personne".
Une autre méthode consiste à utiliser la méthode statique implicite name()
de Enum. name retournera la chaîne exacte utilisée pour créer cette énumération, qui peut être utilisée pour vérifier la chaîne fournie:
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");
}
}
Essai:
System.out.println(Blah.getEnum("B").name());
//it will print B B
inspiration: 10 exemples de Enum en Java
Solution utilisant des bibliothèques Guava. La méthode getPlanet () n'étant pas sensible à la casse, getPlanet ("MerCUrY") renverra 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();
}
}
Dans Java 8, le modèle de carte statique est encore plus simple et constitue ma méthode préférée. Si vous souhaitez utiliser Enum avec Jackson, vous pouvez remplacer toString et l'utiliser à la place de name, puis annotez avec @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);
}
}
Pour compléter les réponses précédentes et aborder certaines des discussions autour des valeurs nulles et NPE, j'utilise Guava Optionals pour traiter les cas absents/invalides. Cela fonctionne très bien pour l'analyse URI/paramètres.
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();
}
}
}
Pour ceux qui ne sont pas au courant, voici quelques informations supplémentaires sur la façon d'éviter la valeur null avec Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional
Méthode O (1) inspirée du code généré économiquement qui utilise un hashmap.
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;
}
}
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;
}
La bibliothèque d'Apache commons-lang a une fonction statique org.Apache.commons.lang3.EnumUtils.getEnum qui mappera une chaîne sur votre type Enum. Même réponse essentiellement que Geoffreys mais pourquoi rouler le vôtre alors qu'il est déjà dans la nature.
Ajoutant à la réponse la mieux notée, avec un utilitaire utile ...
valueOf()
lève deux exceptions différentes dans les cas où il n'aime pas son entrée.
IllegalArgumentException
NullPointerExeption
Si vos exigences ne vous garantissent pas que votre chaîne correspondra définitivement à une valeur d'énumération, par exemple si les données de chaîne proviennent d'une base de données et peuvent contenir une ancienne version de l'énum, vous devrez alors les gérer. souvent...
Voici donc une méthode réutilisable que j'ai écrite et qui nous permet de définir un Enum par défaut à renvoyer si la chaîne que nous passons ne correspond pas.
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;
}
}
Utilisez-le comme ceci:
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
}
Java.lang.Enum
définit plusieurs méthodes utiles, disponibles pour tous les types d'énumération en Java:
name()
pour obtenir le nom de toutes les constantes Enum. Le littéral de chaîne utilisé pour écrire les constantes enum est leur nom.values()
peut être utilisée pour obtenir un tableau de toutes les constantes Enum à partir d'un type Enum.valueOf()
pour convertir toute constante Chaîne en constante Enum en Java, comme indiqué ci-dessous.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
Dans cet extrait de code, la méthode valueOf()
renvoie une constante Enum, type Gender.MALE, qui appelle le nom qui renvoie "MALE"
.
Qu'en est-il de?
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();
}
}
}
Enum est très utile, j'ai beaucoup utilisé Enum
pour ajouter une description de certains champs dans différentes langues, comme dans l'exemple suivant:
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;
}
}
Vous pouvez ensuite récupérer la description de manière dynamique en fonction du code de langue transmis à la méthode getDescription(String lang)
, par exemple:
String statusDescription = Status.valueOf("ACT").getDescription("en");
Comme une version switch
- n'a pas encore été mentionnée, je la présente (en réutilisant l'énumération de 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);
}
}
}
Comme cela ne donne aucune valeur supplémentaire à la méthode valueOf(String name)
, il est logique de définir une méthode supplémentaire si nous voulons avoir un comportement différent. Si nous ne voulons pas élever une IllegalArgumentException
, nous pouvons changer l'implémentation en:
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;
}
}
}
En fournissant une valeur par défaut, nous conservons le contrat de Enum.valueOf(String name)
sans lancer de IllegalArgumentException
de cette manière. En aucun cas, null
ne sera renvoyé. Nous lançons donc un NullPointerException
si le nom est null
et dans le cas de default
si defaultValue
est null
. C'est ainsi que valueOfOrDefault
fonctionne.
Cette approche adopte la conception de l'interface Map
- qui fournit une méthode Map.getOrDefault(Object key, V defaultValue)
à partir de Java 8.
Un autre utilitaire capture en sens inverse. Utiliser une valeur qui identifie cet Enum, pas à partir de son nom.
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;
}
}
Exemple:
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")
renvoie Foo.THREE
, car il utilisera getValue
pour correspondre à "drei", méthode unique publique, non finale et non statique dans Foo. Dans le cas où Foo a plus d'une méthode publique, non finale et non statique, par exemple, getTranslate
qui renvoie "drei", l'autre méthode peut être utilisée: EnumUtil.from(Foo.class, "drei", "getTranslate")
.
J'aime utiliser ce type de processus pour analyser les commandes sous forme de chaînes dans des énumérations. Normalement, l’une des énumérations est "inconnue", il est donc utile de la renvoyer lorsque les autres ne sont pas trouvées (même sur une base insensible à la casse) plutôt que null (ce qui signifie qu’il n’ya pas de valeur). Par conséquent, j'utilise cette approche.
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;
}
Le moyen le plus rapide d’obtenir le nom d’énum est de créer une mappe de texte et de valeur enum au démarrage de l’application et d’obtenir le nom, appelez la fonction 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.toString());
}
}
public static String getEnumName(String text) {
return map.get(text.toLowerCase());
}
}