enum.values ​​() - est un ordre des énumérations renvoyées déterministe

105

J'ai une énumération SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Est-ce que SOME_ENUM.values()toujours revenir les énumérations dans l'ordre des déclarations ENUM: EN_ONE, EN_TWO, EN_THREE? Est-ce une règle ou il n'est pas garanti qu'elle ne sera pas modifiée dans les prochaines versions de JDK?

Skarab
la source
1
J'effectue une itération sur mon énumération pour remplir une liste, que j'ai lu à un autre endroit du code en parcourant cette énumération.
Skarab
11
@MitchWheat Pour la même raison que vous vous fiez à un ordre de préservation de List: parce que le JDK est un outil qui vous donne certaines garanties et s'appuyer sur ces garanties vous aide à écrire un code plus succinct et meilleur. Certes, la question "Est-elle garantie de ne pas changer?" Il est impossible de répondre, vous ne pouvez certainement pas vous fier à cela, rien n'a cette garantie.
Fletch

Réponses:

144

La spécification du langage Java utilise ce langage explicite:

@return un tableau contenant les constantes de ce type enum, dans l'ordre où elles sont déclarées [Source]

Donc, oui, ils seront retournés dans l'ordre de déclaration. Il convient de noter que l'ordre peut changer avec le temps si quelqu'un change de classe, alors soyez très prudent sur la façon dont vous l'utilisez.

GaryF
la source
1
Si quelqu'un ajoute une valeur au milieu dans une version de code ultérieure, cela pourrait vous arranger, car cela changerait la valeur ordinale d'autres éléments (voir la méthode Enum.ordinal ()). Il est préférable de ne pas compter sur la position ordinale comme mécanisme de sérialisation (c'est-à-dire, ne pas la stocker dans la base de données) pour cette raison.
Matt
1
Lien vers la source de cette spécification?
Dan Grahn
Java 8 doc
Drew Stephens
16

Oui, il est garanti de les retourner dans cet ordre.

Cependant, évitez de vous fier à cela et à la ordinal()valeur, car elle peut changer après l'insertion de nouveaux éléments, par exemple.

Bozho
la source
+1 pour les sages conseils. Concernant ordinal (), Effective Java suggère d'ajouter un champ membre au type enum.
Id
9

Il est déterminé par l'ordre dans lequel vos valeurs sont déclarées. Cependant, il n'y a aucune garantie que vous (ou quelqu'un d'autre) ne réorganiserez pas / n'insérerez / supprimerez pas les valeurs à l'avenir . Vous ne devriez donc pas vous fier à la commande.

Efficace Java 2nd. L'édition dédie son élément 31 à un sujet étroitement lié: utilisez les champs d'instance au lieu des ordinaux :

Ne dérivez jamais une valeur associée à une énumération de son ordinal; stockez-le plutôt dans un champ d'instance.

Péter Török
la source
3
"aucune garantie que quelqu'un ne réorganisera pas les valeurs à l'avenir" - mais c'est exactement pourquoi je veux me fier à la commande :-)! Je souhaite pouvoir réorganiser les articles à l'avenir et ainsi modifier le comportement de mon programme. Bloch a raison de ne pas se fier à l'ordinal et si l'exemple du demandeur implique vraiment des énumérations comme EN_TWO, alors il se fie à l'ordinal et ne devrait pas le faire. Mais se fier à la commande est parfaitement bien. En fait, comme l'ordre est garanti, créer un champ spécifiquement pour l'ordre reviendrait à écrire du code redondant, le genre de chose que les livres comme Effective Java vous disent de ne pas faire.
Fletch
@Fletch, désolé, je ne vous suis pas tout à fait. Pour moi, cela semble que vous essayez d'utiliser enumdans un but auquel il n'était pas destiné.
Péter Török
disons que vous avez la fameuse énumération "Planet". Dans votre interface utilisateur, vous souhaitez répertorier les planètes dans l'ordre de leur distance par rapport au soleil. Comment pouvez-vous y parvenir au mieux? Je classerais les constantes de planète dans le bon ordre dans la classe enum, puis énumérerais simplement l'énumération dans l'interface utilisateur. Puisque la commande est fiable, cela fonctionnera. C'est le genre de chose dont je parle. Si un jour la Terre se rapproche du Soleil que Mars, bien sûr, dans un tel moment, la première chose à faire dans votre esprit chaleureux sera de maintenir votre code! Vous allez donc dans votre classe Planet et déplacez EARTH avant MARS.
Fletch
@Fletch, la Terre est déjà plus proche du Soleil que de Mars ;-) mais je comprends ce que tu veux dire. Cependant, dans ce cas, l'ordre des planètes est en fait une fonction de leur distance moyenne du Soleil, qui n'est pas un simple ordinal, donc à mon humble avis, il devrait mieux être stocké comme un champ distinct pour chaque planète. Ensuite, vous pouvez demander à un comparateur trivial de comparer les planètes en fonction de leur distance moyenne au Soleil et de les commander à l'aide de ce comparateur. Ceci est à mon humble avis une solution propre et infaillible. Alors que votre solution se rompt dès que par exemple un nouveau collègue décide que les planètes doivent évidemment être listées par ordre alphabétique ;-)
Péter Török
1
Hahaha ermm oui ben de toute façon c'est une conspiration, il n'y a pas de Mars. Au départ, j'allais utiliser Saturne mais je ne me souvenais pas de quelles planètes il se trouve, mais le plan de Mars semble s'être retourné contre lui :-). Quoi qu'il en soit ... dans ce cas, un comparateur serait bien mais a l'inconvénient d'exiger plus de code, évidemment. Je pense que si vous vous fiez à l'ordre du code source, documenter cela dans les commentaires de classe serait une bonne chose. Votre collègue pourrait même le lire.
Fletch
7

Les autres réponses sont bonnes, mais ne commentez pas ceci:

"Est-ce une règle ou il n'est pas garanti qu'elle ne sera pas modifiée dans les prochaines versions de Jdk?"

Je ne crois pas qu'il existe des garanties sur les futurs JDK, donc vous ne devriez même pas vous en soucier. Il n'y aurait aucun moyen de les appliquer, les futurs responsables JDK pourraient simplement décider de renoncer à ces garanties. C'est comme le système parlementaire de Westminster: "Aucun Parlement ne peut lier un futur parlement".

Cela dit, l'histoire du JDK révèle une excellente cohérence. Ils n'apportent pas beaucoup de changements de rupture, vous pouvez donc être assez sûr que le comportement actuel spécifié (pas seulement observé) sera préservé.

Fletch
la source