Java null periksa mengapa menggunakan == daripada .equals ()

125

Di Jawa saya diberitahu bahwa ketika melakukan pemeriksaan null seseorang harus menggunakan == daripada .equals (). Apa alasannya?

Jim Jeffries
sumber
12
Hal termudah adalah mencoba memeriksa equals()dan melihat nol . Ketika Anda mencobanya akan langsung terlihat jelas
Goran Jovic
Omong-omong, pencarian google dengan kata kunci "java null check" (tanpa tanda kutip) memberi saya sebagai salah satu hit teratas utas ini , yang memiliki info yang sama dengan jawaban di sini.
Mitch Schwartz

Jawaban:

179

Mereka adalah dua hal yang sangat berbeda. ==membandingkan referensi objek, jika ada, yang dikandung oleh variabel. .equals()memeriksa untuk melihat apakah dua objek sama menurut kontraknya untuk apa arti persamaan. Sangat mungkin untuk dua contoh objek berbeda untuk menjadi "sama" menurut kontrak mereka. Dan kemudian ada detail kecil yang karena equalsadalah sebuah metode, jika Anda mencoba untuk memanggilnya pada nullreferensi, Anda akan mendapatkan NullPointerException.

Misalnya:

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
TJ Crowder
sumber
maksudmu public int data?
Jé Queue
@ Xepoch: Tidak, saya biasanya tidak membuat bidang publik (meskipun tidak terlalu penting untuk contoh ini). Mengapa?
TJ Crowder
@TJ Crowder "Mereka adalah dua hal yang sama sekali berbeda .." secara umum ya. Namun, implementasi default keduanya sama, jika pemahaman saya benar. Melihat kode sumber, .equals () pada dasarnya melakukan pemeriksaan ==. hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/classes/…
Ayush
1
@Ayush - Itu defaultnya Object, ya. Ini diganti oleh sejumlah besar kelas JDK. Tapi yang penting bukanlah tentang implementasi, ini tentang semantik. (Catatan tambahan: JDK7 sangat ketinggalan zaman.)
TJ Crowder
Benar, itu masuk akal, hanya ingin menjelaskan.
Ayush
38

jika Anda memanggil .equals()pada nullAnda akan mendapatkanNullPointerException

Jadi selalu disarankan untuk memeriksa nullity sebelum menjalankan metode di mana pun itu berlaku

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

Lihat juga

Jigar Joshi
sumber
34
Contoh Anda umumnya lebih baik ditulis sebagai if ("hi".equals(str)).
ColinD
3
@ user368186: intinya bukanlah apakah metode sama dengan menyertakan pemeriksaan null. Jika referensi objek Anda nol, panggilan someObject.equals(null)akan memunculkan a NullPointerExceptiontanpa pernah memasukkan metode sama dengan.
Dave Costa
2
@ColinD Setuju hanya mendemonstrasikan di sini
Jigar Joshi
2
Selalu disarankan untuk menghindari nol dengan cara apa pun, jadi Anda tidak perlu pemeriksaan nol sama sekali;).
fwielstra
2
Anda selalu dapat menggunakan Objects.equals(a, b)Itu tidak akan menaikkan NullPointerException, tetapi masih bergantung pada metode "sama" dari "a" dan "b"
Dominik Minc
29

Selain jawaban yang diterima ( https://stackoverflow.com/a/4501084/6276704 ):

Sejak Java 1.7, jika Anda ingin membandingkan dua Objek yang mungkin nol, saya merekomendasikan fungsi ini:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

Kelas ini terdiri dari metode utilitas statis untuk beroperasi pada objek. Utilitas ini mencakup metode null-safe atau null-tolerant untuk menghitung kode hash suatu objek, mengembalikan string untuk suatu objek, dan membandingkan dua objek.

Sejak: 1.7

Biru
sumber
2
Hanya untuk membuatnya lebih terlihat untuk orang lain (lihat jawaban chin90 ini atau javadoc ): Objects.equals(null, null)akan kembali true- keep itu dalam pikiran.
Thomas
20

Di Java 0 atau null adalah tipe sederhana dan bukan objek.

Metode sama dengan () tidak dibuat untuk tipe sederhana. Jenis sederhana dapat dicocokkan dengan ==.

pengguna523859
sumber
4
suara positif untuk jawaban aktual yang paling berguna dibandingkan dengan jawaban "NullPointerException akan dikembalikan" yang jelas.
volk
4
foo.equals(null)

Apa yang terjadi jika foo bernilai null?

Anda mendapatkan NullPointerException.

Nick Orton
sumber
3

Jika variabel Object adalah null, seseorang tidak dapat memanggil metode equals () di atasnya, sehingga pemeriksaan referensi objek null adalah tepat.

Jé Queue
sumber
2

Jika Anda mencoba memanggil sama dengan pada referensi objek null, maka Anda akan mendapatkan pengecualian pointer nol.

SAYA
sumber
2

Menurut sumber , tidak masalah apa yang digunakan untuk implementasi metode default:

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

Tetapi Anda tidak bisa yakin tentang equalsdi kelas khusus.

DixonD
sumber
Itu penting, karena equalshanya dapat mengembalikan falseatau menyebabkan NullPointerException(atau sesuatu yang berbeda jika equalsmetode yang diganti tidak masuk akal).
Tom
2

Jika kita menggunakan metode => .equals

if(obj.equals(null))  

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

Jika obj Anda menjadi null, maka Object akan mengeluarkan Null Point Exception.

jadi kita harus menggunakan ==

if(obj == null)

itu akan membandingkan referensi.

AKT
sumber
2

Object.equals aman null, namun perlu diketahui bahwa jika dua objek null, object.equals akan mengembalikan true jadi pastikan untuk memeriksa bahwa objek yang Anda bandingkan bukan null (atau tahan nilai null) sebelum menggunakan object.equals for perbandingan.

String firstname = null;
String lastname = null;

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

Contoh potongan di atas akan kembali sama!

chin90
sumber
Seperti yang dinyatakan oleh JavaDoc (selalu bijaksana untuk membacanya): Consequently, if both arguments are null, true is returned. ...:)
Thomas
1

Karena equal adalah fungsi yang diturunkan dari kelas Objek, fungsi ini membandingkan item dari kelas. jika Anda menggunakannya dengan null maka akan mengembalikan false karena konten kelas tidak null. Selain itu == membandingkan referensi ke suatu objek.

danny.lesnik
sumber
Nah, hasilnya hanya bisa falseatau NullPointerException(jika equalstidak diganti menjadi sesuatu yang buruk).
Tom
1

berikut adalah contoh di mana str != nulltetapi str.equals(null)saat menggunakanorg.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




EDIT: di sini adalah kelas 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;
    }  
}
dina
sumber
Masalahnya di sini adalah yang field.equals(null)mengembalikan true. Ini merusak perilaku Java yang biasa dan karena itu membingungkan. Ini seharusnya hanya bekerja untuk field.equals("null"), setidaknya dalam sudut pandang saya. Saya tidak tahu mengapa para pengembang perpustakaan berpikir, bahwa ini akan bagus untuk didukung.
Tom
Btw, kalimat pertama Anda memiliki masalah tata bahasa dan tidak jelas apa yang Anda maksud dengannya. Apakah maksud Anda "Ini adalah contoh di mana str != nulldan str.equals(null)kembali truesaat menggunakan org.json ."?
Tom
Saya pikir itu karena jsonObjectberisi kunci "field" itu sebabnya fieldbukan null, ia memiliki referensi yang berisi json.org.JSONObject$Null objek
dina
Ya, tapi saya tidak akan memperlakukan Nullseperti nulldan akan menggunakan "null"sebagai gantinya. Tapi saya rasa mereka melakukan itu untuk menghindari permintaan Strings. Tetapi bahkan dengan lib itu, field.equals(null)masih hampir selalu menjadi masalah: P.
Tom
0

Jadi saya tidak pernah bingung dan terhindar dari masalah dengan solusi ini:

if(str.trim().length() <=0 ) {
   // is null !
}
Matheus Marques
sumber
5
Jika str null ini akan menjadi NPE
typoerrpr
Selain itu string kosong ( ""memiliki panjang 0) adalah sesuatu yang sama sekali berbeda dari nullreferensi (yaitu tanpa string).
Thomas
0

Saya telah menemukan kasus ini tadi malam.
Saya menentukan bahwa:

Tidak ada metode equals () untuk null
Jadi, Anda tidak bisa memanggil metode yang tidak ada jika Anda tidak memiliki
- >>> Itulah alasan mengapa kami menggunakan == untuk memeriksa null

Neo_
sumber
0

Kode Anda melanggar hukum Demeter. Itulah mengapa lebih baik melakukan refaktorisasi desain itu sendiri. Sebagai solusinya, Anda dapat menggunakan Opsional

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

di atas adalah untuk memeriksa hierarki suatu objek jadi cukup gunakan

Optional.ofNullable(object1) 

jika Anda hanya memiliki satu objek untuk diperiksa

Semoga ini membantu !!!!

Akitha_MJ
sumber
-3

Anda selalu bisa melakukannya

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

Ini pertama-tama akan memeriksa referensi objek dan kemudian memeriksa objek itu sendiri yang menyediakan referensi isnt null.

Kevin Orriss
sumber
if (str == null || str.equals (null) || str.equals (""))
Lou Morda
saya menggunakan jawaban Anda dan menambahkan cek untuk string kosong! jika saya tidak salah, null dan "" bukanlah hal yang sama.
Lou Morda
4
Apakah tidak sepenuhnya berlebihan untuk menambahkan cek ke-2 untuk null?
Justin Rowe
2
@JustinRowe Ini tidak hanya mubazir, itu juga sangat salah. Tolong, jangan pernah melakukan hal seperti itu x.equals(null).
Tom
@ Tom, JustinRowe tolong lihat jawaban saya di atas mengapa ini tidak mubazir atau menyelesaikan sampah stackoverflow.com/questions/4501061/…
dina