Java-Enum-Mitglieder vergleichen: == oder equals ()?

1736

Ich weiß, dass Java-Enums zu Klassen mit privaten Konstruktoren und einer Reihe öffentlicher statischer Mitglieder kompiliert werden. Beim Vergleich zweier Mitglieder einer bestimmten Aufzählung habe ich immer .equals()z

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

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

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

Welchen Operator sollte ich verwenden?

Matt Ball
quelle
7
Ich bin gerade auf eine sehr ähnliche Frage gestoßen
Matt Ball
39
Ich bin überrascht, dass in allen Antworten (insbesondere in der Antwort von Polygenelubricants, in der ausführlich erklärt wird, warum == funktioniert) ein weiterer großer Vorteil von == nicht erwähnt wurde: Es wird deutlich, wie Aufzählungen funktionieren (als fester Satz von Singleton) Objekte). Bei Gleichheit kann man denken, dass es irgendwie mehrere Instanzen derselben Aufzählungsalternative geben kann.
Stuart Rossiter
6
Halte es einfach. "==" ist besser lesbar und funktioniert, da Aufzählungen standardmäßig Singleton sind. Ref
lokesh

Antworten:

1577

Beide sind technisch korrekt. Wenn Sie sich den Quellcode ansehen .equals(), wird er einfach aufgeschoben ==.

Ich benutze ==jedoch, da dies null sicher sein wird.

Reverend Gonzo
quelle
64
Persönlich mag ich 'Null-Sicherheit' nicht, die als Grund für die Verwendung von == genannt wird.
Nivas
257
@Nivas: warum nicht? Sorgen Sie sich gerne um die Reihenfolge Ihrer Argumente (was nur für den Vergleich von Konstanten von links gilt, wie in Pascals Antwort)? Möchten Sie immer überprüfen, ob ein Wert nicht null ist, bevor .equals()Sie ihn eingeben? Ich weiß, dass ich es nicht tue.
Matt Ball
86
Denken Sie daran, dass beim Lesen Ihres Codes das "==" für den Leser möglicherweise falsch erscheint, bis er losgeht und die Quelle für den betreffenden Typ überprüft und dann feststellt, dass es sich um eine Aufzählung handelt. In diesem Sinne ist es weniger ablenkend, ".equals ()" zu lesen.
Kevin Bourrillion
60
@ Kevin - Wenn Sie keine IDE verwenden, mit der Sie Typen beim Anzeigen der Quelle direkt anzeigen können, betrügen Sie sich selbst - kein Problem mit einer geeigneten IDE.
MetroidFan2002
63
Manchmal wird Code überarbeitet und es ist möglich, dass eine Aufzählung durch eine Klasse ersetzt wird. Zu diesem Zeitpunkt ist == nicht mehr garantiert, dass sie korrekt ist, während equals weiterhin nahtlos funktioniert. Aus diesem Grund ist gleich eindeutig eine bessere Wahl. Wenn Sie Nullsicherheit wünschen (weil Sie auf einer Codebasis arbeiten, die nicht geschrieben wurde, um die Verwendung von Nullen zu minimieren), sind Apache ObjectUtils oder Guavas Objects # gleich (oder Sie können Ihre eigenen rollen). Ich werde das Wort "Performance" nicht einmal erwähnen, aus Angst, dass mich jemand zu Recht mit einem Donald Knuth-Buch schlägt.
Laszlok
1113

Kann ==verwendet werden enum?

Ja: Aufzählungen verfügen über strenge Instanzsteuerelemente, mit denen Sie ==Instanzen vergleichen können. Hier ist die Garantie der Sprachspezifikation (Hervorhebung von mir):

JLS 8.9 Enums

Ein Aufzählungstyp hat keine anderen Instanzen als die durch seine Aufzählungskonstanten definierten.

Es ist ein Fehler beim Kompilieren, wenn versucht wird, einen Aufzählungstyp explizit zu instanziieren. Die final cloneMethode in Enumstellt sicher, dass enumKonstanten niemals geklont werden können, und die spezielle Behandlung durch den Serialisierungsmechanismus stellt sicher, dass niemals doppelte Instanzen als Ergebnis der Deserialisierung erstellt werden. Die reflektierende Instanziierung von Aufzählungstypen ist verboten. Zusammen stellen diese vier Dinge sicher, dass keine Instanzen eines enumTyps existieren, die über die durch die enumKonstanten definierten hinausgehen .

Da es nur eine Instanz jeder enumKonstante gibt, ist es zulässig, den ==Operator anstelle der equalsMethode zu verwenden, wenn zwei Objektreferenzen verglichen werden, wenn bekannt ist, dass mindestens eine von ihnen auf eine enumKonstante verweist . (Die equalsMethode in Enumist eine finalMethode, die lediglich super.equalsihr Argument aufruft und das Ergebnis zurückgibt, wodurch ein Identitätsvergleich durchgeführt wird.)

Diese Garantie ist stark genug, die Josh Bloch empfiehlt. Wenn Sie darauf bestehen, das Singleton-Muster zu verwenden, können Sie es am besten implementieren, indem Sie ein einzelnes Element verwenden enum(siehe: Effektive Java 2nd Edition, Punkt 3: Erzwingen Sie die Singleton-Eigenschaft mit a privater Konstruktor oder ein Aufzählungstyp ; auch Thread-Sicherheit in Singleton )


Was sind die Unterschiede zwischen ==und equals?

Zur Erinnerung muss gesagt werden, dass dies im Allgemeinen ==KEINE Alternative ist equals. Wenn dies jedoch der Fall ist (z. B. bei enum), sind zwei wichtige Unterschiede zu berücksichtigen:

== wirft nie NullPointerException

enum Color { BLACK, WHITE };

Color nothing = null;
if (nothing == Color.BLACK);      // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException

== wird zur Kompilierungszeit einer Typpompatibilitätsprüfung unterzogen

enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };

if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);      // DOESN'T COMPILE!!! Incompatible types!

Sollte ==gegebenenfalls verwendet werden?

Bloch erwähnt ausdrücklich, dass unveränderliche Klassen, die die richtige Kontrolle über ihre Instanzen haben, ihren Kunden garantieren können, dass sie ==verwendbar sind. enumwird ausdrücklich als Beispiel erwähnt.

Punkt 1: Betrachten Sie statische Factory-Methoden anstelle von Konstruktoren

[...] es ermöglicht einer unveränderlichen Klasse, die Garantie zu geben, dass keine zwei gleichen Instanzen existieren: a.equals(b)genau dann, wenn a==b. Wenn eine Klasse diese Garantie übernimmt, können ihre Clients den ==Operator anstelle der equals(Object)Methode verwenden, was zu einer verbesserten Leistung führen kann. Aufzählungstypen bieten diese Garantie.

Zusammenfassend sind die Argumente für die Verwendung von ==on enum:

  • Es klappt.
  • Es ist schneller.
  • Zur Laufzeit ist es sicherer.
  • Beim Kompilieren ist es sicherer.
Polygenschmierstoffe
quelle
27
Nizza Antwort , aber ... 1. Es funktioniert : vereinbart 2. es ist schneller : beweisen es für Aufzählungen :) 3. Es ist sicherer , zur Laufzeit : Color nothing = null;ist IMHO ein Fehler und sollte behoben werden, Ihre Enum hat zwei Werte, nicht drei ( siehe Tom Hawtins Kommentar) 4. Zum Zeitpunkt der Kompilierung ist es sicherer : OK, equalswürde aber trotzdem zurückkehren false. Am Ende kaufe ich es nicht, ich bevorzuge equals()die Lesbarkeit (siehe Kevins Kommentar).
Pascal Thivent
201
Es ist eine schwarze Markierung gegen Java, die einige Leute für foo.equals(bar)lesbarer halten alsfoo == bar
Bennett McElwee
19
Es funktioniert: Bis Sie eine Aufzählung im Rahmen eines Refactorings durch eine Klasse ersetzen müssen. Viel Glück beim Finden des gesamten Codes mit ==, der kaputt geht. Es ist schneller: Auch wenn es wahr (fragwürdig) ist, gibt es dieses Knuth-Zitat über vorzeitige Optimierung. Sicherer zur Laufzeit: "Sicher" ist nicht das erste Wort, das Ihnen in den Sinn kommt, wenn die Verwendung von == das einzige ist, was Sie von einer NullPointerException unterscheidet. Sicherer beim Kompilieren: Nicht wirklich. Es kann Sie vor dem eher elementaren Fehler bewahren, die falschen Typen zu vergleichen, aber wenn Ihre Programmierer so dumm sind, ist "sicher" das Einzige, was Sie nicht sind.
Laszlok
35
"Wenn Ihre Programmierer so dumm sind, ist" sicher "das Einzige, was Sie nicht sind." - Ich stimme diesem Zitat nicht zu. Darum geht es bei der Typprüfung: Verhinderung "dummer" Fehler beim Kompilieren, also noch bevor der Code ausgeführt wird. Selbst kluge Leute machen dumme Fehler, besser einige Garantien als Versprechen.
Ymajoros
7
@laszlok: sicher, aber wenn die Dinge scheitern können, werden sie es einfach tun. Einen Zaun für einige dumme Fehler zu haben, ist immer eine gute Sache. Es gibt viel Raum, um kreativ für weniger triviale Fehler zu sein. Lassen Sie den Compiler diese beheben, bevor Sie jemals versuchen, Ihren Code auszuführen.
Ymajoros
88

Das ==Vergleichen von zwei Aufzählungswerten funktioniert, da für jede Aufzählungskonstante nur ein Objekt vorhanden ist.

Nebenbei bemerkt, es ist eigentlich nicht nötig ==, null-sicheren Code zu schreiben, wenn Sie Ihren folgenden Code schreiben equals():

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

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

Pascal Thivent
quelle
9
Ich mache das, wenn ich .equals()Zeichenfolgenwerte eingebe, aber ich denke immer noch, dass es eine beschissene Art ist, null-sicheren Code zu schreiben. Ich hätte viel lieber einen Operator (oder eine Methode, aber ich weiß, dass [null object] .equals in Java aufgrund der Funktionsweise des Punktoperators niemals null-sicher sein wird), der unabhängig von der immer null-sicher ist Reihenfolge, in der es verwendet wird. Semantisch sollte der Operator "equals" immer pendeln.
Matt Ball
2
Nun, da Java nicht über den Safe Navigation-Operator von Groovy ( ?.) verfügt, werde ich diese Vorgehensweise weiterhin verwenden, wenn ich sie mit Konstanten vergleiche, und TBH finde ich sie nicht beschissen, vielleicht nur weniger "natürlich".
Pascal Thivent
32
Eine nullAufzählung ist normalerweise ein Fehler. Sie haben diese Aufzählung aller möglichen Werte und hier ist eine andere!
Tom Hawtin - Tackline
8
Mit Ausnahme von Werten, die explizit als kommentiert sind @Nullable, halte ich Compare Constants From The Left für ein Antimuster, da es Unklarheiten darüber verbreitet, welche Werte null sein können oder nicht. Aufzählungstypen sollten fast nie sein @Nullable, daher wäre ein Nullwert ein Programmierfehler. In einem solchen Fall ist es umso wahrscheinlicher, dass Sie Ihren Programmierfehler dort finden, wo Sie zugelassen haben, dass er null ist, je früher Sie NPE auslösen. "Best Practice ... dem Sie unbedingt folgen sollten" ist also eindeutig falsch, wenn es um Aufzählungstypen geht.
Tobias
24
Vergleichen Sie Konstanten von links. Eine bewährte Methode wie das beste Englisch im Yoda-Stil ist.
Maaartinus
58

Wie andere gesagt haben, funktionieren beide ==und .equals()in den meisten Fällen. Die Gewissheit über die Kompilierungszeit, dass Sie keine völlig unterschiedlichen Objekttypen vergleichen, auf die andere hingewiesen haben, ist gültig und vorteilhaft. Die besondere Art des Fehlers beim Vergleichen von Objekten mit zwei verschiedenen Kompilierungszeittypen wird jedoch auch von FindBugs (und wahrscheinlich auch von) gefunden Eclipse / IntelliJ-Inspektionen zur Kompilierungszeit), sodass der Java-Compiler, der dies feststellt, nicht so viel zusätzliche Sicherheit bietet.

Jedoch:

  1. Die Tatsache, dass ==ich nie an NPE denke, ist ein Nachteil von ==. Es sollte kaum jemals eine Notwendigkeit für enumTypen geben null, da jeder zusätzliche Status, über den Sie möglicherweise ausdrücken möchten, nulleinfach enumals zusätzliche Instanz zu hinzugefügt werden kann . Wenn es unerwartet ist null, hätte ich lieber eine NPE als ==stillschweigend falsch zu bewerten. Daher bin ich nicht der Meinung, dass es zur Laufzeit sicherer ist . Es ist besser, sich daran zu gewöhnen, niemals enumWerte sein zu lassen @Nullable.
  2. Das Argument, ==das schneller ist, ist auch falsch. In den meisten Fällen rufen Sie .equals()eine Variable auf, deren Kompilierungszeittyp die Enum-Klasse ist, und in diesen Fällen kann der Compiler wissen, dass dies dasselbe ist wie ==(da enumdie equals()Methode von an nicht überschrieben werden kann) und den Funktionsaufruf optimieren Weg. Ich bin mir nicht sicher, ob der Compiler dies derzeit tut, aber wenn dies nicht der Fall ist und sich insgesamt als Leistungsproblem in Java herausstellt, würde ich den Compiler lieber reparieren, als 100.000 Java-Programmierer ihren Programmierstil entsprechend ändern zu lassen Leistungsmerkmale einer bestimmten Compilerversion.
  3. enumssind Objekte. Für alle anderen Objekttypen ist der Standardvergleich .equals()nicht ==. Ich denke, es ist gefährlich, eine Ausnahme zu machen, enumsweil Sie möglicherweise versehentlich Objekte mit ==anstatt vergleichen equals(), insbesondere wenn Sie eine enumin eine Nicht-Enum-Klasse umgestalten . Im Falle eines solchen Refactorings ist der Punkt Es funktioniert von oben falsch. Um sich davon zu überzeugen, dass eine Verwendung von ==korrekt ist, müssen Sie prüfen, ob der betreffende Wert entweder ein enumoder ein Grundelement ist. Wenn es keine enumKlasse wäre, wäre es falsch, aber leicht zu übersehen, da der Code immer noch kompiliert würde. Der einzige Fall, wenn eine Verwendung von.equals()wäre falsch, wenn die fraglichen Werte primitiv wären; In diesem Fall würde der Code nicht kompiliert, sodass es viel schwieriger ist, ihn zu übersehen. Daher .equals()ist es viel einfacher, als korrekt zu identifizieren, und es ist sicherer gegen zukünftige Refactorings.

Ich denke tatsächlich, dass die Java-Sprache == für Objekte definiert haben sollte, um .equals () auf der linken Seite aufzurufen und einen separaten Operator für die Objektidentität einzuführen, aber so wurde Java nicht definiert.

Zusammenfassend denke ich immer noch, dass die Argumente für die Verwendung .equals()für enumTypen sprechen .

Tobias
quelle
4
Nun, zu Punkt 3 kann ich enumals switchZiel verwenden, damit sie etwas Besonderes sind. Strings sind auch etwas Besonderes.
CurtainDog
Die Syntax für switch-Anweisungen enthält weder == noch .equals (), daher verstehe ich nicht, worum es Ihnen geht. In Punkt 3.) geht es darum, wie einfach es ist, Code für einen Leser zu überprüfen. Die Gleichheitssemantik von switch-Anweisungen ist korrekt, solange die switch-Anweisung kompiliert wird.
Tobias
17

Ich benutze lieber ==anstelle von equals:

Ein weiterer Grund, zusätzlich zu den anderen, die hier bereits besprochen wurden, ist, dass Sie einen Fehler einführen können, ohne es zu merken. Angenommen, Sie haben diese Aufzählung, die genau gleich 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
}

Nehmen wir dann an, Sie verwenden die Gleichheit wie item.categoryfolgt, first.pckg.Categoryaber Sie importieren die zweite Aufzählung ( second.pckg.Category) anstelle der ersten, ohne es zu merken:

import second.pckg.Category;
...

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

So werden Sie immer falsefällig, ist eine andere Aufzählung, obwohl Sie wahr erwarten, weil item.getCategory()ist JAZZ. Und es könnte etwas schwierig zu sehen sein.

Wenn Sie stattdessen den Operator verwenden ==, wird ein Kompilierungsfehler angezeigt:

operator == kann nicht auf "second.pckg.Category", "first.pckg.Category" angewendet werden.

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 
Pau
quelle
Sehr gute Punkte, die Sie erwähnt haben. Also würde ich myenum.value () anwenden und dann den == Vergleich für die NPE-Sicherheit durchführen.
Java Main
14

Hier ist ein grober Timing-Test, um die beiden zu vergleichen:

import java.util.Date;

public class EnumCompareSpeedTest {

    static enum TestEnum {ONE, TWO, THREE }

    public static void main(String [] args) {

        Date before = new Date();
        int c = 0;

        for(int y=0;y<5;++y) {
            for(int x=0;x<Integer.MAX_VALUE;++x) {
                if(TestEnum.ONE.equals(TestEnum.TWO)) {++c;}
                if(TestEnum.ONE == TestEnum.TWO){++c;}              
            }
        }

        System.out.println(new Date().getTime() - before.getTime());
    }   

}

Kommentieren Sie die IFs einzeln aus. Hier sind die beiden Vergleiche von oben in zerlegtem Bytecode:

 21  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 24  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 27  invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
 30  ifeq 36

 36  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 39  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 42  if_acmpne 48

Der erste (gleich) führt einen virtuellen Aufruf aus und testet den Rückgabewert vom Stack. Das zweite (==) vergleicht die Objektadressen direkt vom Stapel. Im ersten Fall gibt es mehr Aktivität.

Ich habe diesen Test mehrmals mit beiden IFs nacheinander durchgeführt. Das "==" ist etwas schneller.

ChrisCantrell
quelle
Ich vermute, dass die Compiler-Verzweigungsvorhersage diesen Test ungültig machen könnte. Ein intelligenter Compiler würde erkennen, dass beide if-Anweisungen immer als falsch ausgewertet werden, und somit mehrere Vergleiche vermeiden. Ein wirklich kluger Compiler könnte sogar erkennen, dass die Werte in den y- und x-Schleifen keinen Einfluss auf das Ergebnis haben und das Ganze optimieren ...
Darrel Hoffman
Es könnte, aber es tut es definitiv nicht. Ich zeige den tatsächlich vom Compiler generierten Bytecode in meiner Antwort.
ChrisCantrell
Sie sind beide verwirrt. :-) Die Verzweigungsvorhersage funktioniert zur Laufzeit, sodass der unterschiedliche Bytecode nicht besonders relevant ist. In diesem Fall würde die Verzweigungsvorhersage jedoch beiden Fällen gleichermaßen helfen .
Vidstige
7
Wen interessiert das? Wenn Sie während eines Videospiels nicht tausende Male Enums in einer Schleife vergleichen, ist die zusätzliche Nanosekunde bedeutungslos.
user949300
Der Bytecode ist für die Leistung ziemlich irrelevant, es sei denn, Sie erzwingen den interpretierten Modus. Schreiben Sie einen JMH- Benchmark, um sicherzustellen , dass die Leistung genau gleich ist.
Maaartinus
10

Im Falle einer Aufzählung sind beide richtig und richtig !!

Suraj Chandran
quelle
7

tl; dr

Eine weitere Option ist die Objects.equalsDienstprogrammmethode.

Objects.equals( thisEnum , thatEnum )

Objects.equals für Null-Sicherheit

gleich operator == anstelle von .equals ()

Welchen Operator sollte ich verwenden?

Eine dritte Option ist die statische equalsMethode für die ObjectsDienstprogrammklasse , die Java 7 und höher hinzugefügt wurde .

Beispiel

Hier ist ein Beispiel mit der MonthAufzählung.

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

Leistungen

Ich finde ein paar Vorteile für diese Methode:

  • Null-Sicherheit
  • Kompakt, lesbar

Wie es funktioniert

Welche Logik wird verwendet Objects.equals?

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

return (a == b) || (a != null && a.equals(b));
Basil Bourque
quelle
6

Es ==ist Unsinn, etwas anderes zu verwenden, als Enum-Konstanten zu vergleichen. Es ist wie ein Vergleich von classObjekten mitequals - tu es nicht!

Es gab jedoch einen bösen Fehler (BugId 6277781 ) in Sun JDK 6u10 und früher, der aus historischen Gründen interessant sein könnte. Dieser Fehler verhinderte die ordnungsgemäße Verwendung ==bei deserialisierten Aufzählungen, obwohl dies wohl eher ein Eckfall ist.

Tomas
quelle
4

Aufzählungen sind Klassen, die eine Instanz (wie Singletons) für jede von public static final field(unveränderlich) deklarierte Aufzählungskonstante zurückgeben, sodass der ==Operator verwendet werden kann, um ihre Gleichheit zu überprüfen, anstatt eine equals()Methode zu verwenden

ΦXocę 웃 Пepeúpa ツ
quelle
1

Der Grund, warum Aufzählungen mit == problemlos funktionieren, liegt darin, dass jede definierte Instanz auch ein Singleton ist. Der Identitätsvergleich mit == funktioniert also immer.

Wenn Sie jedoch == verwenden, weil es mit Aufzählungen funktioniert, ist Ihr gesamter Code eng mit der Verwendung dieser Aufzählung verbunden.

Zum Beispiel: Enums können eine Schnittstelle implementieren. Angenommen, Sie verwenden derzeit eine Aufzählung, die Interface1 implementiert. Wenn es später jemand ändert oder eine neue Klasse Impl1 als Implementierung derselben Schnittstelle einführt. Wenn Sie dann anfangen, Instanzen von Impl1 zu verwenden, müssen Sie aufgrund der vorherigen Verwendung von == viel Code ändern und testen.

Daher ist es am besten, eine bewährte Methode zu befolgen, es sei denn, es gibt einen vertretbaren Gewinn.

Dev Amitabh
quelle
Nizza Antwort, aber bereits erwähnt hier .
Shmosel
Äh. An diesem Punkt wäre die Frage, ob Sie == oder gleich auf einer Schnittstelle verwenden. Dazu alle möglichen Fragen, ob es wirklich sinnvoll ist, eine Implementierung eines unveränderlichen Typs durch eine veränderbare Implementierung zu ersetzen. Und es ist wahrscheinlich ratsam, herauszufinden, was eine gute Praxis ist, bevor Sie sich über einen berechtigten Gewinn Gedanken machen. (imho == ist eine bessere Praxis).
Robin Davies
1

Eine der Sonarregeln ist Enum values should be compared with "==". Die Gründe sind folgende:

Das Testen der Gleichheit eines Aufzählungswerts mit equals()ist absolut gültig, da eine Aufzählung ein Objekt ist und jeder Java-Entwickler weiß, ==dass sie nicht zum Vergleichen des Inhalts eines Objekts verwendet werden sollte. Zur gleichen Zeit mit ==Aufzählungen:

  • bietet den gleichen erwarteten Vergleich (Inhalt) wie equals()

  • ist null-sicherer als equals()

  • Bietet eher eine (statische) Überprüfung zur Kompilierungszeit als eine Laufzeitprüfung

Aus diesen Gründen sollte die Verwendung von ==bevorzugt werden equals().

Last but not least ist die ==on-Aufzählung wohl besser lesbar (weniger ausführlich) als equals().

Mohsen Zamani
quelle
0

Kurz gesagt, beide haben Vor- und Nachteile.

Einerseits hat es Vorteile ==, wie in den anderen Antworten beschrieben.

Wenn Sie jedoch aus irgendeinem Grund die Aufzählungen durch einen anderen Ansatz ersetzen (normale Klasseninstanzen), haben ==Sie Bisse verwendet. (BTDT.)

glglgl
quelle
-1

Ich möchte Polygenschmierstoffe ergänzen Antwort:

Ich persönlich bevorzuge equals (). Aber es gibt die Typpompatibilitätsprüfung. Was ich für eine wichtige Einschränkung halte.

Deklarieren und verwenden Sie eine benutzerdefinierte Funktion in Ihrer Enumeration, um die Typkompatibilität zur Kompilierungszeit zu überprüfen.

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

Damit haben Sie alle Vorteile beider Lösungen: NPE-Schutz, einfach zu lesender Code und Typpompatibilitätsprüfung zur Kompilierungszeit.

Ich empfehle auch, einen UNDEFINED-Wert für enum hinzuzufügen.

Christus
quelle
4
Warum ist diese Lösung besser als ==? Mit erhalten ==Sie NPE-Schutz, einfach zu lesenden Code und Kompatibilitätsprüfung für die Kompilierungszeit, und Sie erhalten all diese, ohne benutzerdefinierte gleichwertige Methoden zu schreiben.
Matt Ball
1
Ein UNDEFINEDWert ist wahrscheinlich eine gute Idee. Natürlich würden Sie in Java 8 Optionalstattdessen ein verwenden.
Tomas
-7

==kann werfen, NullPointerExceptionwenn ein primitiver Typ mit seiner Klassenversion verglichen wird. Zum Beispiel:

private static Integer getInteger() {
    return null;
}

private static void foo() {
    int a = 10;

    // Following comparison throws a NPE, it calls equals() on the 
    // non-primitive integer which is itself null. 
    if(a == getInteger()) { 
        // Some code
    }
}
ayushgp
quelle
2
Der Umfang ist in dieser Frage ziemlich klar und primitive Typen sind nicht im Umfang.
Tom
@ Tom die Diskussion hier ist irreführend, ==die nie werfen kann NPEs. Diese Frage hat genug Antworten, aber dies kann eine gute Referenz sein, falls jemand wie ich, der 2 Stunden gebraucht hat, um zu Bug / Feature zu gelangen, dies liest.
Ayushgp
1
Ich kann keine NPE werfen, wenn Sie das Thema dieser Frage nicht ignorieren. Und selbst wenn Sie diese Antwort hier behalten, glauben Sie, dass jemand mit demselben Problem, das Sie hatten, diese Antwort finden würde, indem er nach etwas anderem sucht? Diese Person müsste nach Aufzählungen suchen, die sie offensichtlich nicht verwendet. Diese Antwort wäre bei dieser Frage sinnvoller
Tom