Porównywanie członków enum Java: == czy równa się ()?

1735

Wiem, że wyliczenia Java są kompilowane do klas z prywatnymi konstruktorami i grupą publicznych członków statycznych. Porównując dwóch członków danego wyliczenia, zawsze używałem .equals()np

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

Jednak właśnie natknąłem się na kod, który używa operatora równości ==zamiast .equals ():

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

Którego operatora powinienem używać?

Matt Ball
źródło
7
Właśnie natknąłem się na bardzo podobne pytanie: stackoverflow.com/questions/533922/…
Matt Ball
39
Dziwi mnie, że we wszystkich odpowiedziach (szczególnie tej z wieloskładnikowych substancji smarujących, która szczegółowo wyjaśnia, dlaczego == działa), że nie wspomniano o kolejnej dużej korzyści = =: że wyraźnie wyjaśnia, jak działa wyliczanie (jako stały zestaw singletonów) obiekty). W przypadku równości skłania do myślenia, że ​​może istnieć wiele instancji tego samego „alternatywnego” wyliczenia.
Stuart Rossiter,
6
Nie komplikuj. „==” jest bardziej czytelne i działa, ponieważ wyliczenia są domyślnie singletonem. Ref
lokesh

Odpowiedzi:

1574

Oba są technicznie poprawne. Jeśli spojrzysz na kod źródłowy .equals(), po prostu odracza się na ==.

Używam ==jednak, ponieważ będzie to bezpieczne.

Wielebny Gonzo
źródło
64
Osobiście nie podoba mi się „zerowe bezpieczeństwo” wymienione jako powód użycia ==.
Nivas,
257
@Nivas: dlaczego nie? Czy lubisz martwić się kolejnością swoich argumentów (która dotyczy tylko porównywania stałych z lewej strony, jak w odpowiedzi Pascala)? Czy lubisz zawsze sprawdzać, czy wartość nie jest zerowa przed .equals()jej wprowadzeniem? Wiem, że nie.
Matt Ball
86
Należy pamiętać, że podczas czytania kodu „==” może wydawać się czytelnikowi niepoprawny, dopóki nie wyłączy się i nie spojrzy na źródło danego typu, a następnie zobaczy, że jest to wyliczenie. W tym sensie czytanie „.equals ()” jest mniej rozpraszające.
Kevin Bourrillion,
60
@Kevin - jeśli nie korzystasz z IDE, które pozwala zobaczyć typy bezpośrednio podczas przeglądania źródła, sam siebie oszukujesz - nie ma problemu z właściwym IDE.
MetroidFan2002,
63
Czasami kod jest refaktoryzowany i możliwe jest, że wyliczenie zostanie zastąpione przez klasę, w którym to momencie == nie jest już gwarantowane, aby było poprawne, podczas gdy równość nadal działa bezproblemowo. Z tego powodu równość jest zdecydowanie lepszym wyborem. Jeśli chcesz zerowego bezpieczeństwa (ponieważ pracujesz na bazie kodu, która nie została napisana, aby zminimalizować użycie zer), istnieje Apache ObjectUtils lub Guava's Objects # równe (lub możesz rzucić własne). Nie wspomnę nawet słowa „wydajność” z obawy, że ktoś słusznie uderzy mnie książką Donalda Knutha.
laszlok
1113

Może ==być używany na enum?

Tak: wyliczenia mają ścisłą kontrolę instancji, która umożliwia ==porównywanie instancji. Oto gwarancja zawarta w specyfikacji języka (moje wyróżnienie):

JLS 8.9 Wyliczenia

Typ wyliczeniowy nie ma innych wystąpień niż te zdefiniowane przez jego stałe wyliczeniowe.

Błędem podczas kompilacji jest próba jawnego utworzenia wystąpienia typu wyliczeniowego. Ta final clonemetoda Enumzapewnia, że enumstałe nigdy nie będą klonowane, a specjalne traktowanie przez mechanizm serializacji gwarantuje, że w wyniku deserializacji nigdy nie zostaną utworzone zduplikowane instancje. Instancja refleksyjna typów wyliczeniowych jest zabroniona. Razem te cztery rzeczy zapewniają, że nie enumistnieją żadne instancje typu poza tymi zdefiniowanymi przez enumstałe.

Ponieważ istnieje tylko jedna instancja każdej enumstałej, dopuszczalne jest użycie ==operatora zamiast equalsmetody podczas porównywania dwóch odniesień do obiektów, jeśli wiadomo, że co najmniej jeden z nich odnosi się do enumstałej . ( equalsMetoda in Enumjest finalmetodą, która po prostu wywołuje super.equalsargument i zwraca wynik, tym samym porównując tożsamość.)

Ta gwarancja jest na tyle silna, że ​​Josh Bloch zaleca, aby upierać się przy używaniu wzorca singletonu, najlepszym sposobem na jego wdrożenie jest użycie jednego elementu enum(patrz: Skuteczna Java 2. wydanie, pozycja 3: Egzekwowanie właściwości singletonu za pomocą prywatny konstruktor lub typ enum ; także bezpieczeństwo wątków w Singleton )


Jakie są różnice między ==i equals?

Dla przypomnienia należy powiedzieć, że ogólnie ==NIE jest realną alternatywą dla equals. Gdy jednak tak jest (np. Z enum), należy wziąć pod uwagę dwie ważne różnice:

== nigdy nie rzuca NullPointerException

enum Color { BLACK, WHITE };

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

== podlega kontroli zgodności typu w czasie kompilacji

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!

Czy ==należy stosować, jeśli dotyczy?

Bloch wspomina w szczególności, że niezmienne klasy, które mają odpowiednią kontrolę nad swoimi instancjami, mogą zagwarantować ==użyteczność ich klientom . enumjest konkretnie wspomniany jako przykład.

Punkt 1: Rozważ statyczne metody fabryczne zamiast konstruktorów

[...] pozwala niezmiennej klasie dać gwarancję, że nie istnieją dwa równe przypadki: a.equals(b)wtedy i tylko wtedy a==b. Jeśli klasa zapewni tę gwarancję, wówczas jej klienci mogą użyć ==operatora zamiast equals(Object)metody, co może spowodować lepszą wydajność. Typy Enum zapewniają tę gwarancję.

Podsumowując, argumenty za korzystanie ==na enumto:

  • To działa.
  • Jest szybsze.
  • Jest bezpieczniejszy w czasie wykonywania.
  • Jest bezpieczniejszy w czasie kompilacji.
środki smarujące wielotlenowe
źródło
27
Dobra odpowiedź, ale ... 1. Działa : uzgodniono 2. jest szybszy : udowodnij to dla wyliczeń :) 3. Jest bezpieczniejszy w czasie wykonywania : Color nothing = null;czy IMHO jest błędem i powinien zostać naprawiony, twoje wyliczenie ma dwie wartości, a nie trzy ( patrz komentarz Toma Hawtina) 4. W czasie kompilacji jest bezpieczniej : OK, ale equalsnadal by powrócił false. Na koniec, ja tego nie kupuję, wolę equals()dla czytelności (patrz komentarz Kevina).
Pascal Thivent
201
To czarny znak w stosunku do Javy, który niektórzy uważają, że foo.equals(bar)jest bardziej czytelny niżfoo == bar
Bennett McElwee
19
Działa: dopóki nie trzeba zastąpić wyliczenia klasą w ramach refaktoryzacji. Powodzenia w znalezieniu całego kodu za pomocą ==, który się psuje. Jest szybszy: nawet jeśli to prawda (wątpliwe), Knuth cytuje przedwczesną optymalizację. Bezpieczniejsze w czasie wykonywania: „Bezpieczne” nie jest pierwszym słowem, które przychodzi na myśl, jeśli użycie == jest jedyną rzeczą, która oddziela cię od NullPointerException. Bezpieczniej w czasie kompilacji: niezupełnie. Może uchronić cię przed dość elementarnym błędem porównywania niewłaściwych typów, ale znowu, jeśli tak głupi są twoi programiści, to „bezpieczna” to jedyna rzecz, której nie jesteś.
laszlok
35
„jeśli tacy głupi są twoi programiści, to„ bezpieczna ”to jedyna rzecz, której nie jesteś”. - Nie zgadzam się z tym cytatem. Na tym właśnie polega sprawdzanie typu: zapobieganie „głupim” błędom podczas kompilacji, a więc nawet przed uruchomieniem kodu. Nawet mądrzy ludzie popełniają głupie błędy, lepiej są pewne gwarancje niż obietnice.
ymajoros,
7
@laszlok: jasne, ale jeśli coś się nie powiedzie, po prostu to zrobi. Posiadanie ogrodzenia dla niektórych głupich błędów jest zawsze dobrą rzeczą. Jest dużo miejsca na kreatywność w przypadku mniej trywialnych błędów, pozwól kompilatorowi zająć się tym zanim spróbujesz uruchomić swój kod.
ymajoros
88

Używanie ==do porównywania dwóch wartości wyliczeniowych działa, ponieważ dla każdej stałej wyliczeniowej jest tylko jeden obiekt.

Na marginesie, w rzeczywistości nie ma potrzeby ==pisania kodu o wartości zerowej, jeśli piszesz coś equals()takiego:

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

Jest to najlepsza praktyka znana jako Porównaj stałe z lewej , którą zdecydowanie powinieneś stosować.

Pascal Thivent
źródło
9
Robię to podczas wprowadzania .equals()wartości ciągów, ale nadal uważam, że jest to kiepski sposób na pisanie kodu o zerowej wartości. Wolałbym mieć operatora (lub metodę, ale wiem, że [obiekt zerowy] .equals nigdy nie będzie zerowo bezpieczny w Javie z powodu tego, jak działa operator kropki), który zawsze jest bezpieczny zerowo, niezależnie od kolejność, w jakiej jest używany. Semantycznie operator „równa się” powinien zawsze dojeżdżać do pracy.
Matt Ball
2
Cóż, ponieważ Java nie ma operatora Bezpiecznej nawigacji Groovy ( ?.), będę nadal korzystać z tej praktyki w porównaniu do stałych i, TBH, nie uważam jej za gównianą, może po prostu mniej „naturalną”.
Pascal Thivent
32
nullEnum jest zwykle błąd. Masz wyliczenie wszystkich możliwych wartości, a oto kolejna!
Tom Hawtin - tackline
8
Z wyjątkiem wartości, które są wyraźnie opatrzone adnotacjami jako @Nullable, uważam, że porównywanie stałych z lewej strony jest antypatternem, ponieważ rozprzestrzenia on niejednoznaczność co do tego, które wartości mogą być zerowe. Typy wyliczeniowe prawie nigdy nie powinny być @Nullable, więc wartość zerowa byłaby błędem programowania; w takim przypadku, im szybciej wyrzucisz NPE, tym bardziej prawdopodobne jest, że znajdziesz błąd programowy w miejscu, w którym pozwoliłeś mu być zerowy. Zatem „najlepsza praktyka ... którą zdecydowanie powinieneś zastosować” jest po prostu błędna, jeśli chodzi o typy wyliczeniowe.
Tobias
24
Porównaj stałe od lewej, najlepszą praktyką, taką jak najlepszy angielski w stylu Yoda.
maaartinus
58

Jak mówili inni, zarówno ==i .equals()praca w większości przypadków. Pewność czasu kompilacji, że nie porównujesz całkowicie różnych typów obiektów, na które wskazali inni, jest ważna i korzystna, jednak szczególny rodzaj błędu porównywania obiektów dwóch różnych typów czasu kompilacji znalazłby również FindBugs (i prawdopodobnie Inspekcja czasu kompilacji Eclipse / IntelliJ), więc znalezienie kompilatora Java nie zapewnia tak dużego bezpieczeństwa.

Jednak:

  1. Fakt, że ==nie rzuca NPE w moim umyśle jest wadą z ==. Prawie nigdy nie powinna istnieć potrzeba istnienia enumtypów null, ponieważ każdy dodatkowy stan, który możesz chcieć wyrazić, nullmoże zostać dodany do enumdodatkowej instancji. Jeśli jest to nieoczekiwanie null, wolałbym mieć NPE niż ==dyskretną ocenę na fałsz. Dlatego nie zgadzam się z tym, że jest bezpieczniejsza w czasie wykonywania ; lepiej jest przyzwyczaić się do tego, aby nigdy nie pozwalać na to, by enumwartości były @Nullable.
  2. Argument, który ==jest szybszy, jest również fałszywy. W większości przypadków będzie zadzwonić .equals()na zmienną, której typ kompilacji czas jest klasa enum, aw tych przypadkach kompilator może wiedzieć, że to jest taki sam jak ==(ponieważ enum„s equals()metoda nie może być zmienione) i można zoptymalizować wywołanie funkcji z dala. Nie jestem pewien, czy kompilator obecnie to robi, ale jeśli tak nie jest i okazuje się, że jest to ogólnie problem z wydajnością w Javie, wolę naprawić kompilator niż pozwolić 100 000 programistów Java zmienić swój styl programowania, aby pasował cechy wydajności konkretnej wersji kompilatora.
  3. enumssą obiektami. Dla wszystkich innych typów obiektów standardowe porównanie .equals()nie jest ==. Wydaje mi się, że tworzenie wyjątków jest niebezpieczne, enumsponieważ ==zamiast tego equals()możesz przypadkowo porównać obiekty , szczególnie jeśli enumprzekształcisz an w klasę nie-enum. W przypadku takiego refaktoryzacji to działa punkt z góry jest błędny. Aby przekonać się, że użycie ==jest poprawne, musisz sprawdzić, czy dana wartość jest albo enumprymitywna; gdyby nie była to enumklasa, byłoby źle, ale łatwo ją przeoczyć, ponieważ kod nadal się kompilował. Jedyny przypadek, w którym użycie.equals()błędem byłoby, gdyby dane wartości były prymitywne; w takim przypadku kod nie zostałby skompilowany, więc o wiele trudniej go przeoczyć. W związku z tym .equals()jest o wiele łatwiejszy do zidentyfikowania jako poprawny i bezpieczniejszy w stosunku do przyszłych refaktoryzacji.

Właściwie uważam, że język Java powinien zdefiniować == na Objects, aby wywołać .equals () na wartości po lewej stronie i wprowadzić osobny operator dla tożsamości obiektu, ale nie tak zdefiniowano Javę.

Podsumowując, nadal uważam, że argumenty są na rzecz korzystania .equals()z enumtypów.

Tobiasz
źródło
4
Cóż, jeśli chodzi o punkt 3, mogę użyć go enumjako switchcelu, aby był trochę wyjątkowy. Strings też są trochę wyjątkowi.
CurtainDog
Składnia instrukcji switch nie zawiera ani == ani .equals (), więc nie rozumiem, o co ci chodzi. Mój punkt 3.) dotyczy łatwości weryfikacji kodu dla czytelnika. Semantyka równości instrukcji przełączania jest poprawna, o ile kompiluje się instrukcja przełączania.
Tobias
17

Wolę używać ==zamiast equals:

Innym powodem, oprócz innych omówionych tutaj, jest to, że możesz wprowadzić błąd, nie zdając sobie z tego sprawy. Załóżmy, że masz wyliczenia, które są dokładnie takie same, ale w oddzielnych pakakach (nie jest to powszechne, ale może się zdarzyć):

Pierwsze wyliczenie :

package first.pckg

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

Drugie wyliczenie:

package second.pckg

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

Następnie załóżmy, że korzystać z równych jak następny w item.categoryktórym jest first.pckg.Categoryjednak importować drugą enum ( second.pckg.Category) zamiast pierwszy nie wiedząc o tym:

import second.pckg.Category;
...

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

Więc zawsze otrzymacie falsenależność, to jest inny wyliczenie, chociaż można oczekiwać, że to prawda, ponieważ item.getCategory()jest JAZZ. I może to być trochę trudne do zobaczenia.

Jeśli więc zamiast tego użyjesz operatora ==, wystąpi błąd kompilacji:

operator == nie można zastosować do „second.pckg.Category”, „first.pckg.Category”

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 
Pau
źródło
Bardzo dobre punkty, o których wspomniałeś. Chciałbym więc użyć myenum.value (), a następnie dokonać porównania == dla bezpieczeństwa NPE.
Java Main
14

Oto przybliżony test czasowy, aby porównać dwa:

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());
    }   

}

Komentuj IFs pojedynczo. Oto dwa porównania z góry w zdemontowanym kodzie bajtowym:

 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

Pierwszy (równy) wykonuje wirtualne wywołanie i testuje wartość logiczną ze stosu. Drugi (==) porównuje adresy obiektów bezpośrednio ze stosu. W pierwszym przypadku jest więcej aktywności.

Przeprowadziłem ten test kilka razy z obydwoma IF po jednym na raz. „==” jest zawsze nieco szybszy.

ChrisCantrell
źródło
Podejrzewam, że przewidywanie gałęzi kompilatora może spowodować, że ten test będzie nieważny. Inteligentny kompilator rozpoznałby, że obie instrukcje if zawsze będą miały wartość false, a tym samym unikną wielokrotnych porównań. Naprawdę inteligentny kompilator może nawet rozpoznać, że wartości w pętli yi x nie będą miały wpływu na wynik i zoptymalizują całość ...
Darrel Hoffman
Mógłby, ale na pewno nie. W mojej odpowiedzi pokazuję kod bajtowy wygenerowany przez kompilator.
ChrisCantrell
oboje jesteście zdezorientowani. :-) Przewidywanie rozgałęzień działa w czasie wykonywania, więc inny kod bajtu nie jest zbyt istotny. Jednak w tym przypadku przewidywanie gałęzi pomogłoby w obu przypadkach jednakowo.
vidstige
7
Kogo to obchodzi? O ile tysiące razy nie porównujesz wyliczeń w pętli podczas gry wideo, dodatkowa nanosekunda nie ma znaczenia.
user949300,
Kod bajtowy jest dość nieistotny dla wydajności, chyba że wymuszasz tryb interpretacji. Napisz test porównawczy JMH, aby zobaczyć, że wydajność jest dokładnie taka sama.
maaartinus
10

W przypadku wyliczenia oba są poprawne i słuszne !!

Suraj Chandran
źródło
7

tl; dr

Inną opcją jest Objects.equalsmetoda użyteczności.

Objects.equals( thisEnum , thatEnum )

Objects.equals dla zerowego bezpieczeństwa

równa się operator == zamiast .equals ()

Którego operatora powinienem używać?

Trzecią opcją jest equalsmetoda statyczna znaleziona w Objectsklasie narzędzia dodanej do Java 7 i nowszych.

Przykład

Oto przykład użycia Monthwyliczenia.

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

Korzyści

Znajduję kilka zalet tej metody:

  • Brak bezpieczeństwa
  • Kompaktowy, czytelny

Jak to działa

Jaka jest logika Objects.equals?

Przekonaj się sam, od kodu Java 10 źródłowego z OpenJDK :

return (a == b) || (a != null && a.equals(b));
Basil Bourque
źródło
6

Używanie czegokolwiek innego niż ==porównywanie stałych wyliczeniowych jest nonsensem. To jak porównywanie classobiektówequals - nie rób tego!

Wystąpił jednak paskudny błąd (BugId 6277781 ) w Sun JDK 6u10 i wcześniejszych, który może być interesujący z powodów historycznych. Ten błąd uniemożliwiał prawidłowe użycie ==zdezrializowanych wyliczeń, chociaż jest to prawdopodobnie nieco narożny przypadek.

Tomas
źródło
4

Wyliczenia są klasami, które zwracają jedną instancję (jak singletony) dla każdej stałej wyliczenia zadeklarowanej przez public static final field(niezmienne), dzięki czemu ==operator może być używany do sprawdzania ich równości, zamiast przy użyciu equals()metody

OcXocę 웃 Пepeúpa ツ
źródło
1

Powodem, dla którego wyliczenia działają łatwo z ==, jest to, że każda zdefiniowana instancja jest także singletonem. Tak więc porównanie tożsamości za pomocą == zawsze będzie działać.

Ale użycie ==, ponieważ działa z wyliczeniami, oznacza, że ​​cały kod jest ściśle powiązany z użyciem tego wyliczenia.

Na przykład: Enums mogą implementować interfejs. Załóżmy, że obecnie używasz wyliczenia, które implementuje interfejs1. Jeśli później ktoś to zmieni lub wprowadzi nową klasę Impl1 jako implementację tego samego interfejsu. Następnie, jeśli zaczniesz używać instancji Impl1, będziesz mieć dużo kodu do zmiany i przetestowania z powodu wcześniejszego użycia ==.

Dlatego najlepiej postępować zgodnie z dobrą praktyką, chyba że istnieje jakikolwiek uzasadniony zysk.

Dev Amitabh
źródło
Ładna odpowiedź, ale już tutaj wspomniana .
shmosel,
Um. W tym momencie pytanie będzie dotyczyło tego, czy użyjesz == czy równa się w interfejsie. Plus wszystkie pytania dotyczące tego, czy naprawdę sensowne jest zastąpienie implementacji typu niezmiennego implementacją zmienną. I prawdopodobnie rozsądnie jest dowiedzieć się, co to jest dobra praktyka, zanim zaczniesz martwić się uzasadnionym zyskiem. (imho == to lepsza praktyka).
Robin Davies,
1

Jedną z zasad Sonaru jest Enum values should be compared with "==". Powody są następujące:

Testowanie równości wartości wyliczeniowej z equals()jest całkowicie poprawne, ponieważ wyliczenie jest Obiektem i każdy programista Java wie, ==że nie należy go używać do porównywania zawartości obiektu. Jednocześnie za pomocą ==wyliczeń:

  • zapewnia takie samo oczekiwane porównanie (treść) jak equals()

  • jest bardziej bezpieczny niż equals()

  • zapewnia sprawdzanie czasu kompilacji (statycznego) zamiast sprawdzania czasu wykonywania

Z tych powodów ==należy preferować użycie equals().

Wreszcie, ==wyliczenia na enum są prawdopodobnie bardziej czytelne (mniej gadatliwe) niż equals().

Mohsen Zamani
źródło
0

Krótko mówiąc, oba mają zalety i wady.

Z jednej strony ma zalety w użyciu == , jak opisano w innych odpowiedziach.

Z drugiej strony, jeśli z jakiegoś powodu zastąpisz wyliczenia innym podejściem (normalne instancje klasy), po użyciu ==cię ugryzie. (BTDT.)

glglgl
źródło
-1

Chcę uzupełnić odpowiedź wieloskładnikowe środki smarne:

Osobiście wolę equals (). Ale to sprawdza zgodność typu. Co uważam za ważne ograniczenie.

Aby sprawdzić zgodność typów w czasie kompilacji, zadeklaruj i użyj niestandardowej funkcji w swoim wyliczeniu.

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

Dzięki temu zyskujesz wszystkie zalety obu rozwiązań: ochronę NPE, łatwy do odczytania kod i kontrolę zgodności typów w czasie kompilacji.

Polecam również dodać wartość UNDEFINED dla wyliczenia.

Chrystus
źródło
4
Dlaczego to rozwiązanie jest lepsze niż ==? Z ==dostać ochronę NPE, łatwy do odczytania kodu i kompilacji typu czas sprawdzania kompatybilności, a otrzymasz wszystkie te bez pisania zwyczaj równa podobny sposób.
Matt Ball
1
UNDEFINEDWartość jest dobrym pomysłem. Oczywiście w Javie 8 użyłbyś Optionalzamiast tego.
Tomas
-7

==może rzucać, NullPointerExceptionjeśli typ pierwotny jest porównywany z wersją klasy. Na przykład:

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
źródło
2
Zakres jest dość jasny w tym pytaniu, a typy pierwotne nie są objęte zakresem.
Tom
@Tom dyskusja, która się tutaj toczy, wprowadza w błąd i ==nigdy nie może się odnieść NPEs. To pytanie ma wystarczającą liczbę odpowiedzi, ale może to być dobre odniesienie na wypadek, gdyby ktoś taki jak ja, który poświęcił 2 godziny, aby dostać się do błędu / funkcji, czyta to.
ayushgp
1
Nie mogę rzucić NPE, jeśli nie zignorujesz tematu tego pytania. A nawet jeśli zatrzymasz tę odpowiedź tutaj, czy myślisz, że ktoś z tym samym problemem znalazłby ją, szukając czegoś innego? Ta osoba musiałaby szukać wyliczeń, których oczywiście nie używają. Ta odpowiedź byłaby bardziej sensowna w przypadku tego pytania: stackoverflow.com/questions/7520432/...
Tom