Java null sprawdź, dlaczego używasz == zamiast .equals ()


125

W Javie powiedziano mi, że podczas sprawdzania wartości null należy używać == zamiast .equals (). Jakie są tego przyczyny?


12
Najłatwiej jest sprawdzić wartość null equals()i zobaczyć. Kiedy spróbujesz, będzie to oczywiste
— Goran Jovic

Nawiasem mówiąc, wyszukiwanie google ze słowami kluczowymi „java null check” (bez cudzysłowów) dało mi jako jedno z najpopularniejszych trafień w tym wątku , który zawiera te same informacje, co odpowiedzi tutaj.
— Mitch Schwartz

Odpowiedzi:


179

To dwie zupełnie różne rzeczy. ==porównuje odniesienie do obiektu, jeśli istnieje, zawarte w zmiennej. .equals()sprawdza, czy dwa obiekty są równe zgodnie z ich umową, co oznacza równość. Jest całkowicie możliwe, aby dwie różne instancje obiektów były „równe” zgodnie z ich umową. A potem jest drobny szczegół, ponieważ equalsjest to metoda, jeśli spróbujesz wywołać ją w nullodwołaniu, otrzymasz plik NullPointerException.

Na przykład:

class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null

masz na myśli public int data?
— Jé Queue

@Xepoch: Nie, generalnie nie tworzę pól publicznych (chociaż tak naprawdę nie ma to znaczenia w tym przykładzie). Czemu?
— TJ Crowder

@TJ Crowder "To dwie zupełnie różne rzeczy ..." ogólnie tak. Jednak domyślna implementacja obu jest taka sama, jeśli moje rozumienie jest poprawne. Patrząc na kod źródłowy, .equals () w zasadzie sprawdza ==. hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/…
— Ayush

1
@Ayush - to jest domyślne ustawienie Object, tak. Jest jednak zastępowany przez dużą liczbę klas JDK. Ale nie chodzi o implementację, chodzi o semantykę. (Nota boczna: JDK7 jest bardzo nieaktualny.)
— TJ Crowder

Racja, to ma sens, chciałem tylko wyjaśnić.
— Ayush

38

jeśli powołać .equals()na nulldostanieszNullPointerException

Dlatego zawsze zaleca się sprawdzenie nieważności przed wywołaniem metody, gdziekolwiek ma to zastosowanie

if(str!=null && str.equals("hi")){
 //str contains hi
}  

Zobacz także


34
Twój przykład jest ogólnie lepiej napisany jako if ("hi".equals(str)).
— ColinD

3
@ user368186: nie chodzi o to, czy metoda equals obejmuje sprawdzenie wartości null. Jeśli odwołanie do obiektu ma wartość null, wywołanie someObject.equals(null)wywoła a NullPointerExceptionbez wprowadzania metody equals.
— Dave Costa

2
@ColinD Zgadzam się, tylko pokazuję tutaj
— Jigar Joshi

2
Zawsze zaleca się unikanie wartości null za wszelką cenę, więc w ogóle nie potrzebujesz sprawdzania wartości null;).
— fwielstra

2
Zawsze możesz użyć Objects.equals(a, b)It nie zgłosi wyjątku NullPointerException, ale nadal zależy to od metody "równej" metody "a" i "b"
— Dominik Minc

29

Oprócz zaakceptowanej odpowiedzi ( https://stackoverflow.com/a/4501084/6276704 ):

Od Java 1.7, jeśli chcesz porównać dwa obiekty, które mogą być zerowe, polecam tę funkcję:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

Ta klasa składa się ze statycznych metod narzędziowych do wykonywania operacji na obiektach. Te narzędzia obejmują metody null-safe lub null-tolerant do obliczania kodu skrótu obiektu, zwracania ciągu dla obiektu i porównywania dwóch obiektów.

Od: 1.7


2
Aby uczynić go bardziej widocznym dla innych (patrz odpowiedź chin90 lub JavaDoc ): Objects.equals(null, null)powróci true- miej to na uwadze.
— Thomas

20

W Javie 0 lub null to typy proste, a nie obiekty.

Metoda equals () nie jest tworzona dla typów prostych. Proste typy można dopasować za pomocą ==.


4
głosuj za właściwą odpowiedź, która jest najbardziej użyteczna, w przeciwieństwie do oczywistej odpowiedzi „NullPointerException zostanie zwrócona” herp derp.
— volk

4
foo.equals(null)

Co się stanie, jeśli foo jest zerowe?

Otrzymasz NullPointerException.


3

Jeśli zmienna Object ma wartość null, nie można wywołać na niej metody equals (), dlatego poprawne jest sprawdzenie odwołania do obiektu null.


2

Jeśli spróbujesz wywołać equals w odwołaniu do obiektu o wartości null, zostanie zgłoszony wyjątek wskaźnika o wartości null.


2

Według źródeł nie ma znaczenia, czego użyć do domyślnej implementacji metody:

public boolean equals(Object object) {
    return this == object;
}

Ale nie możesz być tego pewien equalsw klasie niestandardowej.


Ma to znaczenie, ponieważ equalsmoże tylko zwrócić falselub spowodować a NullPointerException(lub coś innego, jeśli zastąpiona equalsmetoda jest nonsensowna).
— Tom

2

Jeśli użyjemy metody => .equals

if(obj.equals(null))  

// Which mean null.equals(null) when obj will be null.

Gdy twój obiekt będzie zerowy, zgłosi wyjątek punktu zerowego.

więc powinniśmy użyć ==

if(obj == null)

porówna referencje.


2

Object.equals jest null bezpieczny, należy jednak pamiętać, że jeśli dwa obiekty są puste, object.equals zwróci wartość true, więc przed użyciem object.equals dla porównanie.

String firstname = null;
String lastname = null;

if(Objects.equals(firstname, lastname)){
    System.out.println("equal!");
} else {
    System.out.println("not equal!");
}

Przykładowy fragment powyżej zwróci wartość równą!


Jak stwierdzono w JavaDoc (zawsze mądrze jest je przeczytać): Consequently, if both arguments are null, true is returned. ...:)
— Thomas

1

Ponieważ equal to funkcja wywodząca się z klasy Object, funkcja ta porównuje elementy tej klasy. jeśli użyjesz go z null, zwróci false, ponieważ zawartość klasy nie jest pusta. Dodatkowo == porównuje odniesienie do obiektu.


Cóż, wynik może być tylko falselub NullPointerException(jeśli equalsnie zostanie zastąpiony czymś złym).
— Tom

1

tutaj jest przykład gdzie, str != nullale str.equals(null)podczas używaniaorg.json

 JSONObject jsonObj = new JSONObject("{field :null}");
 Object field = jsonObj.get("field");
 System.out.println(field != null);        // => true
 System.out.println( field.equals(null)); //=> true
 System.out.println( field.getClass());  // => org.json.JSONObject$Null




EDYCJA: oto klasa org.json.JSONObject $ Null :

/**
 * JSONObject.NULL is equivalent to the value that JavaScript calls null,
 * whilst Java's null is equivalent to the value that JavaScript calls
 * undefined.
 */
private static final class Null {

    /**
     * A Null object is equal to the null value and to itself.
     *
     * @param object
     *            An object to test for nullness.
     * @return true if the object parameter is the JSONObject.NULL object or
     *         null.
     */
    @Override
    public boolean equals(Object object) {
        return object == null || object == this;
    }  
}

Problem polega na tym, że field.equals(null)zwraca prawdę. To łamie zwykłe zachowanie Javy i dlatego jest mylące. To powinno działać field.equals("null"), przynajmniej z mojego punktu widzenia. Nie wiem, dlaczego programiści biblioteki pomyśleli, że warto byłoby to wspierać.
— Tom

Przy okazji, Twoje pierwsze zdanie zawiera błędy gramatyczne i nie jest jasne, co masz na myśli. Czy masz na myśli „Oto przykład, gdzie str != nulli str.equals(null)powrócić truepodczas korzystania z org.json .”?
— Tom

Myślę, że to dlatego, że jsonObjectzawiera klucz "field", dlatego fieldnie jest pusty, ma odniesienie, które zawiera json.org.JSONObject$Null obiekt
— dina

Tak, ale nie traktowałbym Nulljak nulli "null"zamiast tego używałbym . Ale myślę, że zrobili to, aby uniknąć wymagania Stringsa. Ale nawet z tego lib, field.equals(null)to nadal niemal zawsze problem: P.
— Tom

0

Dlatego nigdy się nie mylę i unikam problemów z tym rozwiązaniem:

if(str.trim().length() <=0 ) {
   // is null !
}

5
Jeśli str jest null, będzie to NPE
— typoerrpr

Dodatkowo pusty ciąg ( ""o długości 0) jest czymś zupełnie innym niż nullreferencja (tj. Brak łańcucha).
— Thomas

0

Spotkałem się z tą sprawą zeszłej nocy.
Ustalam, że po prostu:

Nie istnieje metoda equals () dla null
Więc nie możesz wywołać nieistniejącej metody jeśli nie masz
- >>> To jest powód dlaczego używamy == do sprawdzenia null


0

Twój kod łamie prawo Demeter. Dlatego lepiej zreformować sam projekt. Aby obejść ten problem, możesz użyć opcjonalnego

   obj = Optional.ofNullable(object1)
    .map(o -> o.getIdObject11())
    .map(o -> o.getIdObject111())
    .map(o -> o.getDescription())
    .orElse("")

powyżej służy do sprawdzenia hierarchii obiektu, więc po prostu użyj

Optional.ofNullable(object1) 

jeśli masz tylko jeden obiekt do sprawdzenia

Mam nadzieję że to pomoże !!!!


-3

Zawsze możesz to zrobić

if (str == null || str.equals(null))

Spowoduje to najpierw sprawdzenie odwołania do obiektu, a następnie sprawdzenie samego obiektu, podając, że odwołanie nie jest null.


if (str == null || str.equals (null) || str.equals (""))
— Lou Morda

Wykorzystałem twoją odpowiedź i dodałem czek na pusty ciąg! jeśli się nie mylę, null i „” to nie to samo.
— Lou Morda,

4
Czy dodawanie drugiego sprawdzenia pod kątem wartości null nie jest całkowicie zbędne?
— Justin Rowe

2
@JustinRowe To jest nie tylko zbędne, ale także bardzo złe. Proszę, nigdy nie rób czegoś takiego x.equals(null).
— Tom

@Tom, JustinRowe proszę zobaczyć moją odpowiedź wyżej, dlaczego nie jest to zbędne, ani kompletne śmieci stackoverflow.com/questions/4501061/...
— Dina
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.