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


125

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


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

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


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


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 ==.


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.


3

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


2

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


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.


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.


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!


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.


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

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 !
}

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


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 !!!!


-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.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.