La comparaison de Java enum membres: == ou equals()?
Je sais que Java enums sont compilés pour les classes avec les constructeurs privés et un tas de public static membres. Lorsque l'on compare les deux membres d'une enum, j'ai toujours utilisé des .equals()
, par exemple
public useEnums(SomeEnum a)
{
if(a.equals(SomeEnum.SOME_ENUM_VALUE))
{
...
}
...
}
Cependant, je viens de tomber sur un code qui utilise l'opérateur = ==
au lieu de .equals():
public useEnums2(SomeEnum a)
{
if(a == SomeEnum.SOME_ENUM_VALUE)
{
...
}
...
}
De l'opérateur qui est celui que je dois utiliser?
- J'ai simplement tombé sur une question très semblable: stackoverflow.com/questions/533922/...
- Je suis surpris que dans toutes les réponses (en particulier celui d'polygenelubricants, qui explique en détail pourquoi == œuvres) qu'un autre gros avantage de l' == n'a pas été mentionné: qu'il rend explicite la façon dont les énumérations de travail (comme un ensemble fixe d'objets singleton). Avec est égale à elle conduit à penser qu'il peut en quelque sorte être plusieurs instances de la même enum '"alternative" flottant autour.
- Garder les choses simples. "==" est plus lisible et cela fonctionne parce que les énumérations sont singleton par défaut. Ref
Vous devez vous connecter pour publier un commentaire.
Les deux sont techniquement correct. Si vous regardez le code source de
.equals()
, il suffit simplement de s'en remet donc à==
.- Je utiliser
==
, cependant, cela peut être null coffre-fort..equals()
ing-il? Je sais que je n'ai pas.enum
les noms sont écrits dans toutes les capitales... donc si quelqu'un vient à travers un nom de toutes les capitales, n'est-il pas raisonnable de croire qu'il s'agit d'unfinal
primitive (c'est à dire uneint
oulong
) ou unenum
, soit de ce qui c'est correct d'utiliser==
sur?MyEnum.CONSTANT_ONE != MyEnum.CONSTANT_ONE
est vrai.Enum#equals()
, vous trouvez un tel argument non valide. À l'intérieur deEnum#equals()
c'est tout simplement de faire==
, ce qui signifie, dans le cas où la classe remplacé par le chargeur de classe, à la fois==
etequals
pas (sauf si vous écrivez votre propre est égale pour votre enum qui est rarement un choix judicieux). Donc, sur l'aspect que vous avez mentionné,equals
est rien de mieux que de==
.==
surequals()
. Bien sûr, il est une préférence personnelle pour le poids "au moment de la Compilation de vérification de type" vs "la Facilité de remplacement d'un enum avec une classe" mais je ne peut tout simplement pas d'accord sur vous garder sur la mention ""avec == ... pour aucune bonne raison"X
et un appel de méthodeX.equals(x)
pour une chaînex
. PuisX
ai refait dans un enum. La méthode a été brisé, mais personne n'a remarqué depuis longtemps.equals()
.Peut
==
être utilisé surenum
?Oui: les énumérations ont serré instance de contrôle qui vous permet d'utiliser
==
de comparer les instances. Voici la garantie fournie par la spécification du langage (accent mis par moi):Cette garantie est suffisamment forte pour que Josh Bloch recommande, si vous insistez sur l'utilisation d'un singleton, la meilleure façon de la mettre en œuvre est l'utilisation d'un seul élément
enum
(voir: Efficace Java 2nd Edition, Point 3: Appliquer le singleton de la propriété avec un constructeur privé ou un type enum; aussi Fil de sécurité dans Singleton)Quelles sont les différences entre
==
etequals
?Comme un rappel, il doit être dit qu'en général,
==
n'est PAS une alternative viable àequals
. Quand il est, cependant (comme avecenum
), il y a deux différences importantes à prendre en compte:==
jamais jetteNullPointerException
==
est sous réserve de la compatibilité du type de vérifier au moment de la compilationDevrait
==
être utilisé le cas échéant?Bloch mentionne spécifiquement que immuables classes qui ont le contrôle de leurs instances peuvent garantir à leurs clients que
==
est utilisable.enum
est spécifiquement mentionné pour illustrer.Pour résumer, les arguments pour l'utilisation de
==
surenum
sont:Color nothing = null;
est à mon humble avis un bug et doit être fixe, votre enum en a deux, pas trois (voir Tom Hawtin commentaire) 4. C'est plus sûr au moment de la compilation : OK, maisequals
serait encore de retourfalse
. À la fin, I de ne pas l'acheter, je préfèreequals()
pour la lisibilité (voir Kevin commentaire).null
argument est faible, parce quenull
est controversée pour commencer (C. A. R. Hoare "milliards de dollars erreur", etc). Voir aussi ma question: stackoverflow.com/questions/2887761/... // je pense que le type de compilation vérification de la compatibilité est importante et est beaucoup mieux que "silencieusement à défaut" au moment de l'exécution par le retourfalse
. Je ne suis vraiment pas concernées par la vitesse avantage, car il n'est pas susceptible d'être important; je suis contente de répéter ce que Bloch a dit.==
même si "silencieusement à l'échec" semble trop fort pour moi). Concernant Bloch point sur la vitesse, je suis bien sûr pas dire qu'il a tort, je ne suis pas convaincu qu'il s'applique pour les énumérations (et il a écrit peut). C'est pourquoi j'ai pensé qu'il était légitime de contester vos avantages un peu 🙂 Mais tu as mon +1, c'est encore une belle réponse.foo.equals(bar)
est plus lisible quefoo == bar
==
pour enum. Il n'y a aucune raison à l'appui de l'utilisation deequals()
pour enum, à l'exception des personnes parler de la "convention pour objet de comparaison". Toutefois, compte tenu des particularités sémantiques sens de l'enum, je ne trouve aucun problème de le traiter comme quelque chose de différent. La seule fois que vous devez utiliser est égal, c'est si votre enum est remplacée par certainsequals()
logique, mais je pense que c'est rarement un mouvement valide..equals
tels que la constante est comparée à une potentiellement la valeur null, il ne sera jamais jeter unNullPointerException
. Donc, je ne suis pas sûr que je l'ai acheter dans votre argument que==
ne sera jamais jeter un NPE, car il existe des moyens pour écrire.equals
qui ne permettra pas à jeter non plus..equals()
pour enum ensuite. Je pense toujours que l'argument de "equals() rend plus facile de changer enum pour une classe ordinaire" est fragile. Si vous prenez un tel argument, on devrait même utiliser((Object)primitiveVar).equals(anotherVar)
au lieu deprimitiveVar==anotherVar
pour tous les types primitifs, parce que vous ne savez jamais quand vous voulez remplacer votre utilisation de type primitif à une classe."10" == "10"
est vrai aussi, mais je ne le recommande pas. Encore, corrigez-moi si je me trompe, vous n'avez pas donné tous les arguments qui ne sont pas applicables à la comparaison de chaînes, à droite ?.equals()
est de loin inférieure à==
.== never throws NullPointerException
. Si vous utilisez un Entier et de le comparer avec le '==', que vous pouvez obtenir un NullPointerException lors de l'Entier est null. Lors de la comparaison d'un nombre Entier avec '==', l'Entier nécessite auto-unboxing"10" == "10"
est absolument garanti pour être vrai, par JLS sections 3.10.5 et 15.28.À l'aide de
==
pour comparer deux valeurs enum fonctionne car il n'existe qu'un seul objet pour chaque constante enum.Sur une note de côté, il n'y a effectivement pas besoin d'utiliser
==
à écrire null code de sécurité si vous écrivez votreequals()
comme ceci:Il s'agit d'une pratique connue sous le nom Comparer Les Constantes À Partir De La Gauche que vous avez certainement devraient suivre.
.equals()
ing chaîne de valeurs, mais je pense toujours que c'est une merde à la façon d'écrire null-coffre-fort à code. Je préfère avoir un opérateur (ou une méthode, mais je sais que [null object].équivaut à ne jamais être nul en sécurité dans Java, car de la façon dont l'opérateur point fonctionne) c'est toujours la valeur null-fort, quel que soit l'ordre, il est utilisé dans. Du point de vue sémantique, le "équivaut à" l'exploitant doit toujours commute.?.
), je vais continuer à utiliser cette pratique lors de la comparaison des constantes et, TBH, je ne trouve pas ça terrible, peut-être un peu moins "naturel".null
enum est généralement une erreur. Vous avez cette énumération de toutes les valeurs possibles, et en voici une autre!@Nullable
, je considère que Comparaison des Constantes De La Gauche un antipattern car elle se propage d'ambiguïté sur les valeurs qui peut ou ne peut pas être null. Les types Enum ne devrait jamais être@Nullable
, donc une valeur null serait une erreur de programmation; dans un tel cas, le plus tôt vous jeter NPE, le plus probable que vous allez trouver votre erreur de programmation où vous lui permettent d'être nulle. Donc les "meilleures pratiques ... que vous devez absolument suivre" est simplement faux quand il s'agit de types enum.Comme d'autres l'ont dit, les deux
==
et.equals()
de travail dans la plupart des cas. Le temps de compilation de certitude que vous n'êtes pas en comparant complètement différents types d'Objets que d'autres ont souligné est valide et bénéfique, cependant ce type de bug des objets de comparaison de deux différents moment de la compilation types serait également trouvé par FindBugs (et probablement par Eclipse/IntelliJ moment de la compilation des inspections), de sorte que le compilateur Java de trouver qu'il n'ajoute pas beaucoup plus de sécurité.Cependant:
==
jamais jette des NPE dans mon esprit, c'est un inconvénient de==
. Il ne devrait presque jamais besoin deenum
types denull
, depuis supplémentaires de l'état que vous souhaitez exprimer vianull
peut simplement être ajouté à laenum
comme une instance supplémentaire. Si c'est de façon inattenduenull
, je préfère avoir un NPE que==
silencieusement de l'évaluation à la valeur false. Donc je suis en désaccord avec la , c'est plus prudent au moment de l'exécution opinion; il est préférable de prendre l'habitude de ne jamais laisser lesenum
valeurs@Nullable
.==
est plus rapide est aussi faux. Dans la plupart des cas, vous pourrez appeler.equals()
sur une variable dont le temps de compilation est de type enum classe, et dans ces cas, le compilateur ne peut pas savoir que c'est le même que==
(car unenum
'sequals()
méthode peut pas être modifiée) et permet d'optimiser l'appel de la fonction de distance. Je ne suis pas sûr si le compilateur ne le fait actuellement, mais si ça ne marche pas, et s'avère être un problème de performances en Java dans l'ensemble, alors, je préfère fixer le compilateur de 100 000 programmeurs Java changer leur style de programmation pour répondre à un particulier version compilateur caractéristiques de performance.enums
sont des Objets. Pour tous les autres types d'Objet de la norme de comparaison est.equals()
, pas==
. Je pense qu'il est dangereux de faire une exception pourenums
parce que vous pourriez accidentellement Objets de comparaison avec==
au lieu deequals()
, surtout si vous refactoriser unenum
dans une situation de non-enum class. Dans le cas d'un refactoring, la Il fonctionne point à partir de ci-dessus est faux. Pour vous convaincre que l'utilisation de==
est correcte, vous devez vérifier si la valeur en question est soit unenum
ou un primitif; si c'était un non-enum
classe, il avait mal, mais facile de manquer parce que le code serait encore de la compilation. Le seul cas où une utilisation de.equals()
serait faux est de savoir si les valeurs en question étaient primitives; dans ce cas, le code ne compile pas, donc il est beaucoup plus difficile de manquer. Par conséquent,.equals()
est beaucoup plus facile à identifier comme étant correcte, et est plus sûr contre les futures refactorings.En fait, je pense que le langage Java doivent avoir défini == sur les Objets à l'appel .equals() sur la valeur de la main gauche, et d'introduire un opérateur séparées pour l'identité de l'objet, mais ce n'est pas la façon de Java, a été défini.
En résumé, je pense que les arguments sont en faveur de l'utilisation de
.equals()
pourenum
types.enum
comme unswitch
cible de sorte qu'ils sont un peu spécial.String
s sont un peu trop spécial.Je préfère utiliser
==
au lieu deequals
:Autre raison, en plus des autres déjà discuté ici, est que vous pourriez présenter un bug sans s'en rendre compte. Supposons que vous avez cette énumérations qui est exactement le même, mais séparés pacakges (il n'est pas commun, mais ça peut arriver):
Première enum:
Deuxième enum:
Ensuite, supposons que vous utilisez les égaux comme dans
item.category
qui estfirst.pckg.Category
mais vous importez la deuxième enum (second.pckg.Category
) au lieu de la première sans s'en rendre compte:De sorte que vous aurez toujours
false
en raison de différents enum bien que vous attendez vrai, caritem.getCategory()
estJAZZ
. Et il pourrait être un peu difficile à voir.Donc, si vous utilisez à la place de l'opérateur
==
vous aurez une erreur de compilation:Ici n'est qu'une grossière calendrier de test pour comparer les deux:
Commentaire de l'IFs, un à un. Voici les deux se compare à partir de ci-dessus dans démonté byte-code:
La première (est égal à) effectue un appel virtuel et tests le retour booléen à partir de la pile. La deuxième (==) compare l'objet d'adresses directement à partir de la pile. Dans le premier cas, il n'y a plus d'activité.
J'ai couru ce test plusieurs fois avec les deux IFs, un à la fois. Le "==" est un peu plus rapide.
En cas d'enum les deux sont correctes et à droite!!!!
Utiliser autre chose que le
==
de comparer enum constantes est un non-sens. C'est comme en comparantclass
objets avecequals
– ne pas le faire!Cependant, il y a un méchant bug (BugId Six million deux cent soixante dix sept mille sept cent quatre vingt un) dans Sun JDK 6u10 et antérieures qui pourrait être intéressant pour des raisons historiques. Ce bug empêchait la bonne utilisation de
==
sur désérialisé enums, même si c'est sans doute un peu un cas de coin.Les énumérations sont des classes qui renvoient une instance (comme des singletons) pour chaque énumération constante déclarée par
public static final field
(immuable), de sorte que==
opérateur peut être utilisé pour vérifier leur égalité plutôt que d'utiliserequals()
méthodetl;dr
Une autre option est le
Objets.égal à
méthode utilitaire.Objects.equals
pour les nuls-la sécuritéUne troisième option est la statique
equals
méthode trouvée sur leObjets
classe utilitaire ajoutée à Java 7 et plus tard.Exemple
Voici un exemple d'utilisation de la
Mois
enum.Avantages
J'ai trouver quelques avantages à cette méthode:
true
false
NullPointerException
Comment il fonctionne
Qu'est-ce que la logique utilisée par
Objets.égal à
?Voir pour vous-même, à partir de la Java 10 code source de OpenJDK:
La raison énumérations de travailler facilement avec == est parce que chaque défini instance est également un singleton. Si l'identité de comparaison en utilisant == le sera toujours.
Mais avec==, car il fonctionne avec des enums, toute votre code est étroitement couplé avec l'utilisation du protocole enum.
Par exemple: Enum peut implémenter une interface. Supposons que vous utilisez actuellement un enum qui implémente Interface1. Si plus tard, quelqu'un change ou introduit une nouvelle classe Impl1 comme une mise en œuvre de la même interface. Alors, si vous commencez à l'aide des instances de Impl1, vous aurez beaucoup de code à modifier et de tester à cause de l'utilisation de ==.
Par conséquent, il est préférable de suivre ce qui est considéré comme une bonne pratique à moins qu'il n'y a aucune justifiable gain.
En bref, les deux ont des avantages et des inconvénients.
D'une part, il a des avantages à utiliser
==
, comme décrit dans les autres réponses.D'autre part, si vous pour une raison quelconque remplacer les énumérations avec une approche différente (normal des instances de classe), ayant utilisé
==
vous pique. (BTDT.)equals()
ne peut être substituée à énumérer les classes; c'est unfinal
méthode. Qui irait à l'encontre de l'objectif même de l'utilisation d'un enum. stackoverflow.com/a/2964760/139010Je souhaite compléter polygenelubricants réponse:
Personnellement, je préfère equals(). Mais c'lac le type de contrôle de compatibilité. Je pense que c'est une limitation importante.
À avoir le type de contrôle de compatibilité au moment de la compilation, déclarer et utiliser une fonction personnalisée dans votre enum.
Avec cela, vous avez tous l'avantage de la solution: NPE protection, facile à lire le code et le type de contrôle de compatibilité au moment de la compilation.
Je recommande également d'ajouter une valeur non définie pour l'enum.
==
? Avec==
vous obtenez des entrées en phase nationale de la protection, facile-à-lire le code, et la compilation de type au moment de la vérification de la compatibilité, et vous bénéficiez de tous ceux sans écrire personnalisé est égal à des méthodes de type.UNDEFINED
valeur est probablement une bonne idée. Bien sûr, dans Java 8, vous pourriez utiliser uneOptional
à la place.==
pouvez jeterNullPointerException
si un type primitif est par rapport à sa version de la Classe. Par exemple:==
ne peut jamais jeterNPEs
. Cette question a suffisamment de réponses, mais cela peut être une bonne référence, au cas où quelqu'un comme moi qui a pris 2 heures pour arriver à un bug/feature lit ce.