À l'aide de l'Enum valeur ordinale en cas de commutateur déclaration
Pour mon projet, je suis à l'aide des enums, et j'ai besoin de mettre en œuvre le commutateur instruction de cas, où les nombres ordinaux sont des valeurs spécifiques de l'Enum sont vérifiées, à l'instar de cette façon:
switch ( variable )
{
case MyEnum.A.ordinal():
return true;
case MyEnum.B.ordinal():
return true;
default:
return false;
}
Remarque: les valeurs de retour sont seulement un exemple.
Malheureusement, Eclipse (je suis à l'aide de JDK 1.6) donne à mon erreur de compilation "cas
les expressions doivent être des expressions constantes". Ce que je dois faire? Est-il une autre méthode que l'statique de la table de recherche, décrit ici: Convertir enum ordinale de type enum ?
Je suppose que je ne comprends pas pourquoi vous devez utiliser l'ordinal. Pourquoi ne pouvez-vous pas simplement passer sur l'enum lui-même?
Juste curieux, mais pourquoi êtes-vous en utilisant les énumérations, si vous avez alors les variables qui utilisent les valeurs ordinales? Le point d'énumérations est leur type de sécurité, mais votre variable ne va pas être de type sécurisé.. de toute façon, il pourrait être aussi simple que de prendre la valeur ordinale un public attribut constant au lieu d'y accéder via une méthode de lecture.
Parce que j'ai besoin de valeur ordinale - enum valeurs ne sont pas utiles pour cette raison particulière, parce qu'ils sont sans rapport avec les résultats de l'interrupteur de la déclaration.
Je dois avouer que cela ne fait pas de sens pour moi - Comment la valeur de l'enum être sans rapport avec le résultat de la substitution de la valeur? L'ordinal est juste un indice pour les valeurs enum (un indice qui peut changer si vous ajoutez une nouvelle valeur d'enum) - L'ordinal, de par leur nature n'est plus qu'un transitoire de la propriété de l'enum.
par ce que vous demandez est EnumSet
Juste curieux, mais pourquoi êtes-vous en utilisant les énumérations, si vous avez alors les variables qui utilisent les valeurs ordinales? Le point d'énumérations est leur type de sécurité, mais votre variable ne va pas être de type sécurisé.. de toute façon, il pourrait être aussi simple que de prendre la valeur ordinale un public attribut constant au lieu d'y accéder via une méthode de lecture.
Parce que j'ai besoin de valeur ordinale - enum valeurs ne sont pas utiles pour cette raison particulière, parce qu'ils sont sans rapport avec les résultats de l'interrupteur de la déclaration.
Je dois avouer que cela ne fait pas de sens pour moi - Comment la valeur de l'enum être sans rapport avec le résultat de la substitution de la valeur? L'ordinal est juste un indice pour les valeurs enum (un indice qui peut changer si vous ajoutez une nouvelle valeur d'enum) - L'ordinal, de par leur nature n'est plus qu'un transitoire de la propriété de l'enum.
par ce que vous demandez est EnumSet
OriginalL'auteur DoktorNo | 2011-07-23
Vous devez vous connecter pour publier un commentaire.
C'est la façon dont est fait, à condition d'avoir un sérialisé ordinale quelque part, quelque part. La manière habituelle de persistance d'un enum est par son nom, pas ordinale. Aussi, vous ne devez pas utiliser ordinale dans des circonstances normales, à moins d'essayer de mettre en place quelque chose comme EnumMap/Set. Bien sûr, l'enum peut être juste un port de C pareil les choses et de traiter avec l'inévitable int, a besoin d'une transformation de l'Enum objet.
Suffit d'utiliser
Enum.values()
pour obtenir un tableau commandé parordinal()
, puisque le tableau est cloné à chaque fois, en gardant une ref vers est ok.Viens de remarquer que vous devez seulement le vrai et le faux, qui est un Ensemble de type de comportement. Vous pouvez utiliser java.util.EnumSet ou un simple
long
, si elle se sent courageux (et ne pas avoir plus de 64 enum constantes). par exemple:OriginalL'auteur
Tout d'abord, vous ne devriez pas compter sur l'ordinal que beaucoup. Si possible, faites votre variable d'un
String
(et de se transformer enenum
à l'aide deEnum.valueOf(string)
ou, au mieux, rendreenum
.Si vous ne pouvez vraiment pas, puis utilisez
enum.values()[ordinal]
.Ensuite, utilisez enum dans le commutateur.values()
clones de la matrice, vous feriez mieux de l'avoir dans une variable statique.merci pour le suggstion
vous êtes le bienvenu, mon point est que, le parcours totalement défait le but de cas/instruction switch qui a des performances à l'esprit.
d'accord. Je l'ai ajouté comme une dernière option (bien qu'il ressemble à l'OP veut qu')
OriginalL'auteur Bozho
La réponse des cibles @Riaan commentaire sur la constante vs méthode des énumérations et des raisons de performances et il ne répond directement à l'OP question, de sorte qu'il peut être considéré comme du bruit, je suppose.
Cependant, je crois que c'est une question importante pour comprendre comment les rouages.
J'ai pris de l'indice de référence hors de son exemple et de l'améliorer afin de supprimer la collecte des ordures et de la chaîne de création qui prend plus de 90% du temps d'exécution. Ajouté phase chaude pour assurer hotspot effectivement compile les méthodes.
Il y a un peu plus, l'indice de référence est effectivement callsite test. L'optimisation pour les callsites sont assez différents pour 1, pour 2, pour un peu plus et de plus en plus. Un callsite est une invocation abstraite (ou simplement remplacée) méthode.
Ci-dessous le test avec 6 enums constantes:
Le code a été exécuté w/
-server -XX:+PrintCompilation
options.La différence n'est pas énorme, bien sûr. Cependant ce n'est pas la question intéressante. Si vous testez la version avec 2 enum constantes cependant, le résultat peut être sensiblement différente. Pour les 2 sites d'appel le compilateur génère le code par inlinining la méthode en question. Dans le test ci-dessus qui permettrait d'éliminer l'intégralité de l'appel à booleanValue et peut même faire exécuter le test en O(1).
Le plus drôle, cependant, est de passer de 2 à 3 enum constantes lorsque le compilateur commence à utiliser inline caches et alors la constante, et WOW magie le tout change.
La ligne de fond est: la bonne référence est vraiment difficile et implique une certaine connaissance de la façon dont le JIT compile, lorsque le GC peut être un problème (que ce soit de la supprimer ou de l'embrasser) et ainsi de suite.
Liens:
OriginalL'auteur
suffit d'utiliser la enum constantes:
en supposant que quelque chose comme:
mais méfiez-vous de
NullPointerException
(sivariable
estnull
)OriginalL'auteur Carlos Heuberger
Ce que vous demandez sans doute:
Si vous avez besoin de l'interrupteur dans une méthode dans l'enum lui-même:
Et dans une classe différente:
Il est facile d'oublier de mettre à jour les instructions de commutation si vous ajoutez un autre enum, donc un meilleur pari serait de placer des méthodes de ce genre dans l'enum lui-même et de l'utilisation de la constante spécifique de la méthode d'opération:
De cette façon, si vous ajoutez une nouvelle valeur d'enum, le compilateur va vous rappeler de déclarer la getBooleanValue méthode et il vous suffit d'utiliser
A.getBooleanValue();
partout où vous en avez besoin.Comme il a été souligné dans les commentaires, une autre option est ceci:
C'est une question de préférence et varient en fonction de la situation spécifique. Si vous êtes tout simplement de retourner une valeur pour chaque enum, le constructeur version est plausible, mais je trouve ça moins lisible. Préoccupations au cours de cette exécution mieux est sans fondement comme vous pouvez le voir par les tests:
l'ajout de fonctions comme celle de l'Enum est contre-productif. 1er: vous seriez mieux ayant un champ booléen et c-tor qui initialise la enum (regarde fois mieux et c'est mieux de performance sage - mémoire/temps, chaque constante comme c'est une nouvelle classe); 2e ajoutant plus de cas (fonctions) qui dépendent de l'enum consiste à modifier le modèle de domaine, par exemple, si vous avez besoin d'une fonction qui retourne un booléen. Le gars a juste besoin d'un EnumSet.
Il dépend de la situation. Si c'est aussi simple que de retourner une valeur spécifique, alors oui, vous pourriez faire un constructeur et un champ, mais il serait très semblable dans tous les cas. Concernant les performances, Il n'y a qu'une seule instance de chaque enum champ et le point d'accès compilateur prendra fin en-doublure en plus du code, donc je dirais que ce code serait mieux que d'essayer de coder la fonctionnalité dans une méthode à l'extérieur de l'enum. La différence de performances dans les deux cas serait tellement mineurs qu'il ne fera pas une différence pour 99,9% des cas, en tout cas.
J'ai très peur de l'indice de référence est en quelque sorte encore un autre micro-bencmark-pas-a-droite. L'indice de référence des besoins de chauffe, car la façon dont c'est fait, il comprend le temps de compilation. Aussi le 2e test est susceptible d'inclure certains de collecte des ordures. btw,
MyEnum
ne peut pas être compilé. Je n'ai réécrire l'indice de référence, l'une des constantes est légèrement plus rapide sur 40M éléments, les points de référence passe le plus clair si le temps dans le module et de la Chaîne de création, donc besoin d'un nombre très important d'avoir un effet quelconque.Pas de son offensive, même le standard de l'industrie, des repères sont souvent hors-la marque: azulsystems.com/events/javaone_2002/microbenchmarks.pdf
OriginalL'auteur Riaan Cornelius
Une meilleure solution serait quelque chose comme ceci:
enum:
mise en œuvre:
Homme Pak Hong, Dave ([email protected])
OriginalL'auteur user3615372