Java
fournit une méthode valueOf()
pour chaque objet Enum<T>
, donc on lui donne une enum
comme
public enum Day {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
on peut faire une recherche comme
Day day = Day.valueOf("Monday");
Si la chaîne transmise à valueOf()
ne correspond pas (en respectant la casse) à une valeur Day
existante, une variable IllegalArgumentException
est renvoyée.
Pour faire une correspondance ne respectant pas la casse, on peut écrire une méthode personnalisée dans l’en-tête Day
, par ex.
public static Day lookup(String day) {
for (Day d : Day.values()) {
if (d.name().equalsIgnoreCase(day)) {
return type;
}
}
return null;
}
Existe-t-il un moyen générique, sans utiliser la mise en cache des valeurs ni d’autres objets supplémentaires, d’écrire une seule fois la méthode lookup()
statique (voir la méthode ci-dessus) (c’est-à-dire pas pour chaque enum
), étant donné que la méthode values()
est ajoutée implicitement à la classe Enum<E>
temps de compilation?
La signature d’une telle méthode "générique" lookup()
serait similaire à la méthode Enum.valueOf()
, c’est-à-dire:
public static <T extends Enum<T>> T lookup(Class<T> enumType, String name);
et il implémenterait exactement la fonctionnalité de la méthode Day.lookup()
pour toute enum
, sans qu'il soit nécessaire de réécrire la même méthode pour chaque enum
.
J'ai trouvé difficile d'obtenir le mélange spécial de génériques, mais cela fonctionne.
public static <T extends Enum<?>> T searchEnum(Class<T> enumeration,
String search) {
for (T each : enumeration.getEnumConstants()) {
if (each.name().compareToIgnoreCase(search) == 0) {
return each;
}
}
return null;
}
Exemple
public enum Horse {
THREE_LEG_JOE, GLUE_FACTORY
};
public static void main(String[] args) {
System.out.println(searchEnum(Horse.class, "Three_Leg_Joe"));
System.out.println(searchEnum(Day.class, "ThUrSdAy"));
}
Je pense que le moyen le plus simple et le plus sûr de le faire serait:
Arrays.stream(Day.values())
.filter(e -> e.name().equalsIgnoreCase(dayName)).findAny().orElse(null);
Ou si vous voulez utiliser l'objet de classe, alors:
Arrays.stream(enumClass.getEnumConstants())
.filter(e -> (Enum)e.name().equalsIgnoreCase(dayName)).findAny().orElse(null);
Pour Android et Enum relativement courts, je fais la boucle simple et compare le nom en ignorant le cas.
public enum TransactionStatuses {
public static TransactionStatuses from(String name) {
for (TransactionStatuses status : TransactionStatuses.values()) {
if (status.name().equalsIgnoreCase(name)) {
return status;
}
}
return null;
}
}
Une solution générique serait de garder à la convention que les constantes sont majuscules . (Ou dans votre cas spécifique, utilisez une chaîne de majuscule sur la chaîne de recherche).
public static <E extends Enum<E>> E lookup(Class<E> enumClass,
String value) {
String canonicalValue.toUpperCase().replace(' ', '_');
return Enum<E>.valueOf(enumClass, canonicalValue);
}
enum Day(MONDAY, ...);
Day d = lookup(Day,class, "thursday");
Vous pouvez utiliser la méthode Class
'S getEnumConstants()
, qui renvoie un tableau de tous les types enum, si Class
représente une énumération ou null
sinon.
Retourne les éléments de cette classe enum ou null si cet objet Class ne représente pas un type enum.
Votre ligne améliorée pour la boucle ressemblerait à ceci:
for (T d : enumType.getEnumConstants()) {
et il implémenterait exactement les fonctionnalités de Day.lookup () méthode pour toute énumération, sans qu'il soit nécessaire de réécrire la même méthode pour chaque enum.
Vous pouvez probablement écrire une classe d’utilité pour le faire comme suit.
public class EnumUtil {
private EnumUtil(){
//A utility class
}
public static <T extends Enum<?>> T lookup(Class<T> enumType,
String name) {
for (T enumn : enumType.getEnumConstants()) {
if (enumn.name().equalsIgnoreCase(name)) {
return enumn;
}
}
return null;
}
// Just for testing
public static void main(String[] args) {
System.out.println(EnumUtil.lookup(Day.class, "friday"));
System.out.println(EnumUtil.lookup(Day.class, "FrIdAy"));
}
}
enum Day {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
Cela aurait été bien s'il y avait un moyen d'utiliser Java pour étendre la classe Enum en ajoutant implicitement des méthodes de la même manière que la méthode values (), mais je ne pense pas qu'il soit possible de le faire.
J'utilise cette méthode pour la correspondance insensible à la casse d'une chaîne de caractères avec une énumération Java Day[] days = Day.values();
for(Day day: days) {
System.out.println("MONDAY".equalsIgnoreCase(day.name()));
}