Je connais très bien le C # mais je commence à travailler davantage en Java. Je m'attendais à apprendre que les énumérations en Java étaient fondamentalement équivalentes à celles en C # mais apparemment ce n'est pas le cas. Au départ, j'étais ravi d'apprendre que les énumérations Java pouvaient contenir plusieurs éléments de données, ce qui semble très avantageux ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). Cependant, depuis lors, j'ai trouvé de nombreuses fonctionnalités manquantes qui sont triviales en C #, telles que la possibilité d'attribuer facilement à un élément enum une certaine valeur, et par conséquent la possibilité de convertir un entier en enum sans un effort décent ( c'est-à-dire Convertir une valeur entière en Java Enum correspondant ).
Ma question est donc la suivante: y a-t-il un avantage aux énumérations Java par rapport à une classe avec un tas de champs finaux statiques publics? Ou fournit-il simplement une syntaxe plus compacte?
EDIT: Permettez-moi d'être plus clair. Quel est l'avantage des énumérations Java sur une classe avec un tas de champs finaux statiques publics du même type ? Par exemple, dans l'exemple des planètes au premier lien, quel est l'avantage d'une énumération sur une classe avec ces constantes publiques:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
Pour autant que je sache, la réponse de casablanca est la seule qui satisfait à cela.
public static final
champs, qui peuvent être des valeurs typées et pas nécessairement desint
s.S
, donc maintenant nous parlons de les transmettre probablement à des fonctions, etc. Avons-nous besoin de la sécurité de type? Eh bien, non, mais la plupart des gens considèrent les types de style C de "tout est unvoid*
" bon style et cela peut arrêter les bogues (surtout si vous passez plus d'un paramètre enum / string!). De plus, il place les constantes dans leur propre espace de noms, etc. Contrairement à cela, il n'y a pas de réel avantage à avoir des variables simples.int
s, il n'y a pas de sécurité de type car on pourrait passer n'importe quelle valeur. Les objets typés, en revanche, ne sont pas différents des énumérations en termes de sécurité de type.Réponses:
Techniquement, on pourrait en effet voir les énumérations comme une classe avec un tas de constantes typées, et c'est en fait ainsi que les constantes enum sont implémentées en interne.
enum
Cependant, l' utilisation d'un vous donne des méthodes utiles ( Enum javadoc ) que vous auriez autrement à implémenter vous-même, telles queEnum.valueOf
.la source
.values()
à parcourir la liste des valeurs.switch
instruction descase
déclarations sans réserve.ordinal().
EnumSet
et lesEnumMap
classes.la source
switch
déclarations qui ont motivé à l'origine l'utilisation d'unEnum
.Personne n'a mentionné la possibilité de les utiliser dans les
switch
déclarations; Je vais ajouter cela aussi.Cela permet d'utiliser des énumérations arbitrairement complexes d'une manière propre sans utiliser de séquences
instanceof
potentiellement déroutantesif
ou de valeurs de commutation non-string / int. L'exemple canonique est une machine à états.la source
Le principal avantage est la sécurité du type. Avec un ensemble de constantes, toute valeur du même type intrinsèque pourrait être utilisée, introduisant des erreurs. Avec une énumération, seules les valeurs applicables peuvent être utilisées.
Par exemple
contre
la source
setSize(null)
votre deuxième exemple, mais il est susceptible d'échouer beaucoup plus tôt que l'erreur du premier exemple.Il y a moins de confusion. Prenons
Font
par exemple. Il a un constructeur qui prend le nom de celui queFont
vous voulez, sa taille et son style (new Font(String, int, int)
). À ce jour, je ne me souviens pas si le style ou la taille passe en premier. SiFont
avait utilisé unenum
pour tous ses différents styles (PLAIN
,BOLD
,ITALIC
,BOLD_ITALIC
), son constructeur ressembleraitFont(String, Style, int)
, ce qui empêche toute confusion. Malheureusement, ilenum
n'y en avait pas lorsque laFont
classe a été créée, et puisque Java doit maintenir la compatibilité inverse, nous serons toujours en proie à cette ambiguïté.Bien sûr, ce n'est qu'un argument pour utiliser un
enum
au lieu depublic static final
constantes. Les énumérations sont également parfaites pour les singletons et implémentent un comportement par défaut tout en permettant une personnalisation ultérieure (IE le modèle de stratégie ). Un exemple de ce dernier estjava.nio.file
'sOpenOption
etStandardOpenOption
: si un développeur voulait créer son propre non-standardOpenOption
, il le pourrait.la source
enum
sans utiliser varargs ou aSet
pour en prendre un nombre arbitraire.interface Foo { public void bar(String baz); }
. Quelqu'un fait une classe qui invoquebar
:someFoo.bar(baz = "hello");
. Je change la signature deFoo::bar
enpublic void bar(String foobar)
. Désormais, la personne qui a appelésomeFoo
devra modifier son code si elle souhaite toujours qu'il fonctionne.Il y a beaucoup de bonnes réponses ici, mais aucune ne mentionne qu'il existe des implémentations hautement optimisées des classes / interfaces de l'API Collection spécifiquement pour les énumérations :
Ces classes spécifiques à une énumération n'acceptent que les
Enum
instances (lesEnumMap
seules acceptent lesEnum
s uniquement comme clés), et chaque fois que possible, elles reviennent à une représentation compacte et à la manipulation de bits dans leur implémentation.Qu'est-ce que ça veut dire?
Si notre
Enum
type n'a pas plus de 64 éléments (la plupart desEnum
exemples réels seront qualifiés pour cela), les implémentations stockent les éléments dans une seulelong
valeur, chaqueEnum
instance en question sera associée à un peu de cette longueur de 64 bitslong
. Ajouter un élément à unEnumSet
est simplement définir le bit approprié à 1, le supprimer revient simplement à mettre ce bit à 0. Tester si un élément est dans leSet
est juste un test de masque de bits! Maintenant tu dois aimerEnum
ça!la source
What does this mean?
section. Je savais qu'il y avait un fossé dans la mise en œuvre à la taille 64, mais je ne savais pas vraiment pourquoiexemple:
Limitation des constantes Java
1) Pas de sécurité de type : tout d'abord, ce n'est pas de type sûr; vous pouvez attribuer n'importe quelle valeur int valide à int, par exemple 99 bien qu'il n'y ait pas de pièce pour représenter cette valeur.
2) Aucune impression significative : l'impression de la valeur de l'une de ces constantes imprimera sa valeur numérique au lieu du nom significatif de la pièce, par exemple lorsque vous imprimez NICKLE, il imprimera "5" au lieu de "NICKLE"
3) Pas d'espace de noms : pour accéder à la constante currencyDenom, nous devons préfixer le nom de la classe, par exemple CurrencyDenom.PENNY au lieu d'utiliser simplement PENNY bien que cela puisse également être réalisé en utilisant l'importation statique dans JDK 1.5
Avantage d'énumération
1) Les énumérations en Java sont de type sécurisé et ont leur propre espace de nom. Cela signifie que votre énumération aura un type par exemple "Devise" dans l'exemple ci-dessous et que vous ne pouvez attribuer aucune valeur autre que celle spécifiée dans Constantes Enum.
Currency coin = Currency.PENNY; coin = 1; //compilation error
2) Enum en Java est un type de référence comme la classe ou l'interface et vous pouvez définir un constructeur, des méthodes et des variables dans java Enum, ce qui le rend plus puissant que Enum en C et C ++ comme indiqué dans l'exemple suivant de type Java Enum.
3) Vous pouvez spécifier les valeurs des constantes d'énumération au moment de la création comme indiqué dans l'exemple ci-dessous: public enum Currency {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; Mais pour que cela fonctionne, vous devez définir une variable membre et un constructeur car PENNY (1) appelle en fait un constructeur qui accepte la valeur int, voir l'exemple ci-dessous.
Référence: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
la source
Le premier avantage des énumérations, comme vous l'avez déjà remarqué, est la simplicité de la syntaxe. Mais le point principal des énumérations est de fournir un ensemble bien connu de constantes qui, par défaut, forment une plage et aident à effectuer une analyse de code plus complète grâce à des contrôles de sécurité de type et de valeur.
Ces attributs d'énumérations aident à la fois un programmeur et un compilateur. Par exemple, disons que vous voyez une fonction qui accepte un entier. Que pourrait signifier cet entier? Quel genre de valeurs pouvez-vous transmettre? Vous ne savez pas vraiment tout de suite. Mais si vous voyez une fonction qui accepte enum, vous connaissez très bien toutes les valeurs possibles que vous pouvez transmettre.
Pour le compilateur, les énumérations aident à déterminer une plage de valeurs et à moins que vous n'assigniez des valeurs spéciales aux membres d'énumération, elles sont bien comprises entre 0 et plus. Cela permet de détecter automatiquement les erreurs dans le code grâce à des contrôles de sécurité de type et plus encore. Par exemple, le compilateur peut vous avertir que vous ne gérez pas toutes les valeurs d'énumération possibles dans votre instruction switch (c'est-à-dire lorsque vous n'avez pas de
default
casse et ne gérez qu'une seule valeur d'énumération sur N). Il vous avertit également lorsque vous convertissez un entier arbitraire en enum car la plage de valeurs d'énumération est inférieure à celle d'un entier et cela peut à son tour déclencher des erreurs dans la fonction qui n'accepte pas vraiment un entier. En outre, la génération d'une table de saut pour le commutateur devient plus facile lorsque les valeurs sont comprises entre 0 et plus.Ce n'est pas seulement vrai pour Java, mais aussi pour d'autres langages avec une vérification de type stricte. C, C ++, D, C # sont de bons exemples.
la source
Un ENUM est implictly finale, avec les constructeurs privés, toutes ses valeurs sont du même type ou un sous-type, vous pouvez obtenir toutes ses valeurs à l' aide
values()
, obtient saname()
ouordinal()
valeur ou vous pouvez rechercher un ENUM par numéro ou le nom.Vous pouvez également définir des sous-classes (même si elles sont théoriquement finales, ce que vous ne pouvez pas faire autrement)
la source
enum Avantages:
"comme la possibilité d'attribuer facilement à un élément enum une certaine valeur"
"et par conséquent la possibilité de convertir un entier en enum sans un effort décent" Ajouter une méthode convertissant int en enum qui fait cela. Ajoutez simplement HashMap statique <Integer, EnumX> contenant l' énumération java de mappage .
Si vous voulez vraiment convertir ord = VAL_200.ordinal () en val_200, utilisez simplement: EnumX.values () [ord]
la source
Une autre différence importante est que le compilateur java traite les
static final
champs de types primitifs et String comme des littéraux. Cela signifie que ces constantes deviennent en ligne. C'est similaire auC/C++
#define
préprocesseur. Voir cette question SO . Ce n'est pas le cas avec les énumérations.la source
Vous obtenez une vérification à la compilation des valeurs valides lorsque vous utilisez une énumération. Regardez cette question.
la source
Le plus grand avantage est que les singletons enum sont faciles à écrire et sécurisés pour les threads:
et
les deux sont similaires et ont géré la sérialisation par eux-mêmes en implémentant
plus
la source
Je pense qu'un
enum
ne peut pas êtrefinal
, car sous le capot, le compilateur génère des sous-classes pour chaqueenum
entrée.Plus d'informations De la source
la source
Les énumérations affichées ici présentent de nombreux avantages et je crée actuellement de telles énumérations, comme demandé dans la question. Mais j'ai une énumération avec 5-6 champs.
Dans ce genre de cas, lorsque vous avez plusieurs champs dans les énumérations, il est beaucoup plus difficile de comprendre quelle valeur appartient à quel champ car vous avez besoin de voir le constructeur et le globe oculaire.
La classe avec des
static final
constantes et l'utilisation d'unBuilder
modèle pour créer de tels objets le rendent plus lisible. Mais, vous perdriez tous les autres avantages de l'utilisation d'une énumération, si vous en avez besoin. Un inconvénient de ces classes est, vous devez ajouter lesPlanet
objets manuellement àlist/set
desPlanets.
Je préfère toujours enum à une telle classe, car c'est
values()
pratique et vous ne savez jamais si vous en avez besoin pour l'utiliser dansswitch
ouEnumSet
ouEnumMap
à l'avenir :)la source
Raison principale: les énumérations vous aident à écrire du code bien structuré où la signification sémantique des paramètres est claire et fortement typée au moment de la compilation - pour toutes les raisons que d'autres réponses ont données.
Quid pro quo: en Java prêt à l'emploi, le tableau des membres d'un Enum est définitif. C'est normalement bien car cela aide à valoriser la sécurité et les tests, mais dans certaines situations, cela pourrait être un inconvénient, par exemple si vous étendez le code de base existant peut-être à partir d'une bibliothèque. En revanche, si les mêmes données sont dans une classe avec des champs statiques, vous pouvez facilement ajouter de nouvelles instances de cette classe au moment de l'exécution (vous devrez peut-être également écrire du code pour les ajouter à tout Iterable que vous avez pour cette classe). Mais ce comportement d'Enums peut être changé: en utilisant la réflexion, vous pouvez ajouter de nouveaux membres à l'exécution ou remplacer des membres existants, bien que cela ne devrait probablement être fait que dans des situations spécialisées où il n'y a pas d'alternative: c'est-à-dire que c'est une solution piratée et peut produire des problèmes inattendus, voir ma réponse surPuis-je ajouter et supprimer des éléments d'énumération lors de l'exécution en Java .
la source