2153 Stimmen

Vergleich von Java-Enum-Mitgliedern: == oder equals()?

Ich weiß, dass Java-Enums zu Klassen mit privaten Konstruktoren und einer Reihe von öffentlichen statischen Mitgliedern kompiliert werden. Wenn ich zwei Mitglieder einer gegebenen enum vergleiche, habe ich immer .equals() z.B.

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

Ich bin jedoch gerade auf einen Code gestoßen, der den Gleichheitsoperator verwendet == anstelle von .equals():

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

Welchen Operator sollte ich verwenden?

7 Stimmen

Ich bin gerade über eine sehr ähnliche Frage gestolpert: stackoverflow.com/questions/533922/

73 Stimmen

Ich bin überrascht, dass in all den Antworten (insbesondere in der von polygenelubricants, die detailliert erklärt, warum == funktioniert) ein weiterer großer Vorteil von == nicht erwähnt wurde: dass es explizit macht, wie Enums funktionieren (als eine feste Menge von Singleton-Objekten). Bei equals könnte man meinen, dass es irgendwie mehrere Instanzen der gleichen Enum-'Alternative' geben kann.

3 Stimmen

SomeEnum.SOME_ENUM_VALUE.equals(a) löst niemals eine NullPointerException aus, während a.equals(SomeEnum.SOME_ENUM_VALUE) dies möglicherweise tut.

1983voto

Reverend Gonzo Punkte 37720

Beide sind technisch korrekt. Wenn Sie sich den Quellcode für .equals() wird einfach auf == .

Ich benutze == Da dies jedoch null sicher ist.

122voto

Pascal Thivent Punkte 548176

Verwendung von == um zwei Enum-Werte zu vergleichen, funktioniert, weil es nur ein Objekt für jede Enum-Konstante gibt.

Nebenbei bemerkt, ist es eigentlich nicht nötig, die == nullsicheren Code zu schreiben, wenn Sie Ihre equals() wie diese:

public useEnums(final SomeEnum a) {
    if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
        …
    }
    …
}

Dies ist eine bewährte Praxis, die als Konstanten von links vergleichen die Sie unbedingt befolgen sollten.

72voto

Tobias Punkte 1050

Wie andere bereits gesagt haben, sind beide == y .equals() in den meisten Fällen funktionieren. Die von anderen hervorgehobene Sicherheit, dass man nicht völlig unterschiedliche Objekttypen vergleicht, ist gültig und vorteilhaft, aber die besondere Art des Fehlers beim Vergleich von Objekten zweier unterschiedlicher Kompilierzeittypen würde auch von FindBugs (und wahrscheinlich von Eclipse/IntelliJ-Kompilierzeitinspektionen) gefunden werden, so dass der Java-Compiler, der ihn findet, nicht viel zusätzliche Sicherheit bietet.

Allerdings:

  1. Die Tatsache, dass == nie NPE auslöst, ist in meinen Augen ein Nachteil von == . Es dürfte kaum jemals ein Bedarf bestehen für enum Typen zu sein null da jeder zusätzliche Zustand, den Sie möglicherweise über null kann einfach in die enum als zusätzliche Instanz. Wenn es unerwartet ist null Ich hätte lieber einen NPE als == stillschweigend als false ausgewertet wird. Daher stimme ich nicht mit der es ist sicherer während der Laufzeit Meinung; es ist besser, sich anzugewöhnen, nie zuzulassen enum Werte sein @Nullable .
  2. Das Argument, dass == es schneller ist ebenfalls ein Schwindel. In den meisten Fällen werden Sie anrufen .equals() auf eine Variable, deren Kompilierzeittyp die Enum-Klasse ist, und in diesen Fällen kann der Compiler wissen, dass dies dasselbe ist wie == (weil ein enum 's equals() Methode kann nicht überschrieben werden) und kann den Funktionsaufruf wegoptimieren. Ich bin mir nicht sicher, ob der Compiler dies derzeit tut, aber wenn nicht, und es sich als ein Leistungsproblem in Java insgesamt herausstellt, dann würde ich lieber den Compiler reparieren, als dass 100.000 Java-Programmierer ihren Programmierstil ändern, um sich an die Leistungsmerkmale einer bestimmten Compiler-Version anzupassen.
  3. enums sind Objekte. Für alle anderen Objekttypen lautet der Standardvergleich .equals() , nicht == . Ich denke, es ist gefährlich, eine Ausnahme zu machen für enums denn Sie könnten versehentlich Objekte mit == anstelle von equals() besonders dann, wenn Sie ein Refactoring einer enum in eine Nicht-Enum-Klasse. Im Falle eines solchen Refactorings wird die Es funktioniert Punkt von oben ist falsch. Sich davon zu überzeugen, dass eine Verwendung von == korrekt ist, müssen Sie prüfen, ob der betreffende Wert entweder ein enum oder ein Primitivum; wenn es sich um ein Nicht enum Klasse, wäre es falsch, aber leicht zu übersehen, weil der Code noch kompiliert werden würde. Der einzige Fall, in dem eine Verwendung von .equals() falsch wäre, wenn es sich bei den fraglichen Werten um Primitive handeln würde; in diesem Fall würde der Code nicht kompiliert werden, so dass es viel schwieriger ist, ihn zu übersehen. Folglich, .equals() ist viel einfacher als korrekt zu erkennen und sicherer für zukünftige Refactorings.

Ich denke, die Sprache Java hätte == für Objekte definieren sollen, um .equals() für den linken Wert aufzurufen, und einen separaten Operator für die Objektidentität einführen sollen, aber so wurde Java nicht definiert.

Zusammenfassend lässt sich sagen, dass die Argumente nach wie vor für die Verwendung von .equals() für enum Typen.

27voto

Pau Punkte 13014

Ich bevorzuge die Verwendung von == anstelle von equals :

Ein weiterer Grund, zusätzlich zu den anderen, die hier bereits diskutiert wurden, ist, dass Sie einen Fehler einführen könnten, ohne es zu bemerken. Angenommen, Sie haben diese enums, die genau das gleiche ist, aber in getrennten Paketen (es ist nicht üblich, aber es könnte passieren):

Erste Aufzählung :

package first.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

Zweite Aufzählung:

package second.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

Dann nehmen wir an, Sie verwenden die Gleichheitszeichen wie folgt in item.category das ist first.pckg.Category aber Sie importieren die zweite Aufzählung ( second.pckg.Category ), sondern die erste, ohne es zu merken:

import second.pckg.Category;
...

Category.JAZZ.equals(item.getCategory())

Sie erhalten also immer false due ist ein anderes enum, obwohl man true erwartet, weil item.getCategory() es JAZZ . Und es könnte ein bisschen schwierig zu sehen sein.

Wenn Sie also stattdessen den Operator == erhalten Sie einen Kompilierungsfehler:

Operator == kann nicht auf "zweite.pckg.Kategorie", "erste.pckg.Kategorie" angewendet werden

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory()

22voto

Basil Bourque Punkte 256611

Tl;dr

Eine weitere Möglichkeit ist die Objects.equals Gebrauchsmethode.

Objects.equals( thisEnum , thatEnum )

Objects.equals für Nullsicherheit

Gleichheitsoperator == anstelle von .gleich()

Welchen Operator sollte ich verwenden?

Eine dritte Möglichkeit ist die statische equals Methode, die in der Objects Hilfsklasse hinzugefügt zu Java 7 und später.

Ejemplo

Hier ist ein Beispiel, das die Month enum.

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

Vorteile

Diese Methode hat für mich einige Vorteile:

  • Null-Sicherheit
  • Kompakt, lesbar

Wie es funktioniert

Welche Logik verwendet die Objects.equals ?

Überzeugen Sie sich selbst, von der Java 10-Quellcode von OpenJDK :

return 
    ( a == b ) 
    || 
    ( 
        a != null 
        && 
        a.equals( b )
    )
;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X