Lorsque je travaille avec des variables / paramètres qui ne peuvent prendre qu'un nombre fini de valeurs, j'essaie de toujours utiliser Java enum
, comme dans
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
Tant que je reste dans mon code, cela fonctionne très bien. Cependant, j'ai souvent besoin de m'interfacer avec un autre code qui utilise des valeurs simples int
(ou String
) dans le même but, ou j'ai besoin de lire / écrire depuis / vers une base de données où les données sont stockées sous forme de nombre ou de chaîne.
Dans ce cas, j'aimerais avoir un moyen pratique d'associer chaque valeur d'énumération à un entier, de sorte que je puisse convertir dans les deux sens (en d'autres termes, j'ai besoin d'une "énumération réversible").
Passer de enum à int est facile:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Ensuite, je peux accéder à la valeur int comme BonusType x = MONTHLY; int id = x.id;
.
Cependant, je ne vois pas de bon moyen pour l'inverse, c'est-à-dire passer de int à enum. Idéalement, quelque chose comme
BonusType bt = BonusType.getById(2);
Les seules solutions que je pourrais proposer sont:
- Mettez une méthode de recherche dans l'énumération, qui utilise
BonusType.values()
pour remplir une carte "int -> enum", puis la met en cache et l'utilise pour les recherches. Cela fonctionnerait, mais je devrais copier cette méthode de manière identique dans chaque énumération que j'utilise :-(. - Placez la méthode de recherche dans une classe utilitaire statique. Ensuite, je n'aurais besoin que d'une méthode de «recherche», mais je devrais bricoler avec la réflexion pour que cela fonctionne pour une énumération arbitraire.
Les deux méthodes semblent terriblement maladroites pour un problème aussi simple (?).
Avez-vous d'autres idées / idées?
la source
ordinal()
.ordinal()
peuvent-elles être décidées par vous (c'est-à-dire, ne pouvez-vous pas simplement les utiliser ), ou sont-elles décidées par des forces extérieures?Réponses:
http://www.javaspecialists.co.za/archive/Issue113.html
La solution commence comme la vôtre avec une valeur int dans le cadre de la définition enum. Il continue ensuite à créer un utilitaire de recherche basé sur les génériques:
Cette solution est agréable et ne nécessite pas de `` bidouiller la réflexion '' car elle est basée sur le fait que tous les types enum héritent implicitement de l'interface Enum.
la source
Number
place deByte
, car ma valeur de support peut être plus grande.énumération → int
int → énumération
Chaîne → enum
enum → Chaîne
Remarque:
comme vous le faites remarquer correctement, le
ordinal()
peut être "instable" d'une version à l'autre. C'est la raison exacte pour laquelle je stocke toujours les constantes sous forme de chaînes dans mes bases de données. (En fait, lorsque j'utilise MySql, je les stocke sous forme d' énumérations MySql !)la source
BonusType.valueOf("MONTHLY")
)ordinal()
me semble être une solution problématique, car elle sera interrompue lorsque la liste des valeurs d'énumération est réorganisée ou qu'une valeur est supprimée. De plus, cela n'est pratique que si les valeurs int sont 0 ... n (ce que j'ai souvent trouvé ne pas être le cas).values()
tableau ne fonctionnera que si toutes vos valeurs sont indexées à 0 pour leur id et sont déclarées dans l'ordre. (J'ai testé ceci pour vérifier que si vous déclarezFOO(0), BAR(2), BAZ(1);
celavalues[1] == BAR
etvalues[2] == BAZ
malgré les identifiants passés.)double
).J'ai trouvé cela sur le Web, c'était très utile et simple à mettre en œuvre. Cette solution n'a PAS été faite par moi
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}
la source
Il semble que les réponses à cette question soient obsolètes avec la sortie de Java 8.
la source
Collectors.toMap()
êtreFunctions.identity()
au lieu denull
?org.apache.commons.lang.enums.ValuedEnum;
Pour m'éviter d'écrire des tonnes de code standard ou de dupliquer du code pour chaque Enum, j'ai utilisé Apache Commons Lang à la
ValuedEnum
place.Définition :
Usage:
int -> ValuedEnum:
la source
Vous pourriez peut-être utiliser quelque chose comme
Cela réduirait le besoin de réflexion dans votre classe d'utilité.
la source
Dans ce code, pour une recherche permanente et intense, ayez de la mémoire ou un processus à utiliser, et je sélectionne la mémoire, avec un tableau de conversion comme index. J'espère que c'est utile
la source
Utilisez une interface pour lui montrer qui est le patron.
Et le résultat:
la source
Les deux
.ordinal()
etvalues()[i]
sont instables car ils dépendent de l'ordre des énumérations. Ainsi, si vous changez l'ordre des énumérations ou en ajoutez / supprimez certaines, votre programme serait interrompu.Voici une méthode simple mais efficace pour mapper entre enum et int.
L'application pour les chaînes ne devrait pas être difficile.
la source
Étape 1 Définissez un
interface
EnumConverterÉtape 2
Créer un nom de classe ReverseEnumMap
Étape 3
Allez à votre
Enum
classe etimplement
avecEnumConverter<ContentType>
et bien sûr remplacer les méthodes d'interface. Vous devez également initialiser un ReverseEnumMap statique.Étape 4
Créez maintenant un
Communication
fichier de classe et appelez sa nouvelle méthode pour convertir unEnum
enString
etString
enEnum
. Je viens de mettre la méthode principale à des fins d'explication.Cliquez pour une explication complète
la source
ContentType convert(String pKey)
statique, ce qui supprime le besoin de laCommunication
classe et était plus à mon goût. +1Je ne suis pas sûr que ce soit la même chose en Java, mais les types enum en C sont automatiquement mappés en nombres entiers afin que vous puissiez utiliser le type ou l'entier pour y accéder. Avez-vous déjà essayé d'y accéder simplement avec un entier?
la source
.ordinal()
méthode. (Dans l'autre sens, utilisezBonusType.values()[i]
.) Mais dans l'exemple cité ci-dessus, les index ici et les valeurs extérieures ne coïncident pas.Vraiment bonne question :-) J'ai utilisé une solution similaire à celle de Mr.Ferguson il y a quelque temps. Notre énumération décompilée ressemble à ceci:
Voir cela est évident pourquoi
ordinal()
est instable. C'est lei
dedanssuper(s, i);
. Je suis également pessimiste que vous puissiez penser à une solution plus élégante que celles que vous avez déjà énumérées. Après tout, les énumérations sont des classes comme toutes les classes finales.la source
Par souci d'exhaustivité, voici une approche générique pour récupérer les valeurs d'énumération par index à partir de n'importe quel type d'énumération. Mon intention était de faire en sorte que la méthode ressemble à Enum.valueOf (Class, String) . Fyi, j'ai copié cette méthode à partir d' ici .
Les problèmes liés à l'index (déjà abordés en détail ici) s'appliquent toujours.
la source
MyEnumType.values()
- pas besoin d'une méthode d'assistance statique.la source
J'avais besoin de quelque chose de différent parce que je voulais utiliser une approche générique. Je lis l'énumération vers et à partir de tableaux d'octets. C'est là que je viens avec:
Exemple d'énumérations:
}
la source
Juste parce que la réponse acceptée n'est pas autonome:
Code de support:
Exemple d'utilisation:
la source
donné:
public enum BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}
Bonus de type bonus = ANNUEL;
System.out.println (bonus.Ordinal () + ":" + bonus)
Sortie: 1: ANNUELLE
la source
Si vous avez une voiture de classe
Et la propriété Color est une classe
Et vous voulez convertir Color en Enum
Ajoutez simplement une méthode dans la classe Color pour convertir Color en ColorEnum
et à l'intérieur de ColorEnum implémente la méthode getById ()
Vous pouvez maintenant utiliser un classMap
la source