Java: Bagaimana cara memeriksa apakah objek null?

89

Saya membuat aplikasi yang mengambil gambar dari web. Jika gambar tidak dapat diambil gambar lokal lain harus digunakan.

Saat mencoba menjalankan baris berikut:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

Garis if (drawable.equals (null)) memunculkan pengecualian jika drawable bernilai null.

Adakah yang tahu bagaimana seharusnya nilai drawable diperiksa agar tidak memunculkan pengecualian jika nilainya null dan mengambil gambar lokal (mengeksekusi drawable = getRandomDrawable ())?

Niko Gamulin
sumber
23
Gunakan if (drawable == null) Memanggil metode apa pun pada objek NULL adalah NullPointerException.
diciu
3
Mengapa Anda tidak menulis jawaban biasa dan bukan komentar, diciu?
deamon
@JaredBurrows Jangan mengedit kode dalam pertanyaan dengan cara yang menggagalkan tujuan pertanyaan!
Gilles 'SO- berhenti bersikap jahat'
@Gilles Baca komentar editorial saya, saya membuat kode lebih mudah dibaca.
Jared Burrows
@JaredBurrows Tidak, hasil edit Anda bukanlah perubahan "pemformatan". Anda mengubah kode yang tidak berfungsi yang merupakan objek pertanyaan, menjadi kode kerja yang membuat pertanyaan diperdebatkan.
Gilles 'SO- berhenti bersikap jahat'

Jawaban:

35

Solusi Java 8 yang Diedit:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Anda dapat mendeklarasikan drawable finaldalam kasus ini.

Seperti yang ditunjukkan Chasmo, Android tidak mendukung Java 8 saat ini. Jadi solusi ini hanya mungkin dalam konteks lain.

deamon
sumber
7
Mungkin bukan ide yang bagus - Anda akan kembali ke Fortran 60 di mana kedua sisi kondisional dievaluasi, lalu hanya satu yang digunakan. Ini buruk jika cabang yang tidak digunakan memiliki perhitungan apa pun, yang selalu benar, jadi ini bukan metode yang secara umum berguna. Saya akan memindahkan ketentuan tersebut ke Commonkelas, dan mengizinkan Anda untuk memberikan URL cadangan, dan menjaga tanggung jawab bersama.
Pete Kirkham
1
Contoh ini sekarang sepenuhnya ditulis ulang di Java 8, jadi solusi saya tidak lagi mengalami evaluasi yang tidak berguna (seperti yang ditunjukkan @PeteKirkham dalam solusi asli saya).
deamon
1
Android tidak mendukung Java 8. Ini hanya mendukung hingga Java 7 (jika Anda memiliki kitkat) dan masih tidak memiliki pemanggilan dinamis, hanya gula sintaks baru. Selain itu, Optional.ofmengandung arti, bahwa nilainya bukan null, sehingga orElseGettidak perlu. Anda harus menggunakan Optional.ofNullabledalam kasus ini.
Martin Seeler
181
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

The equals()Metode pemeriksaan untuk nilai kesetaraan, yang berarti bahwa itu membandingkan isi dari dua benda. Karena nullbukan objek, ini macet saat mencoba membandingkan konten objek Anda dengan konten null.

The ==cek Operator untuk referensi kesetaraan, yang berarti bahwa itu terlihat apakah dua benda yang sebenarnya objek yang sama . Ini tidak membutuhkan objek untuk benar-benar ada; dua objek yang tidak ada ( nullreferensi) juga sama.

Thomas
sumber
56
Saya ingin menambahkan tip yang sangat berharga: Jika Anda memiliki string atau konstanta untuk dibandingkan, selalu tempatkan mereka terlebih dahulu di klausa sama dengan. (if ("coyote" .equals (myDogString))) jauh lebih baik daripada (if (myDogString.equals ("coyote"))) karena dalam kasus kedua myDogString mungkin null dan melempar NPE sementara di kasus pertama tidak tidak masalah jika myDogString adalah null.
Thorsten S.
21
Dikenal sebagai kondisi Yoda: "jika anjing hutan, anjing itu ..."
Thomas
1
Saya juga ingin menambahkan, karena Java 7 ada metode Objects.equals (), sehingga Anda tidak peduli dengan sintaks Yoda
maryokhin
22

Saya menggunakan pendekatan ini:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

Dengan cara ini saya menemukan meningkatkan keterbacaan baris - ketika saya membaca dengan cepat melalui file sumber saya dapat melihat itu adalah pemeriksaan nol.

Berkenaan dengan mengapa Anda tidak dapat memanggil .equals()objek yang mungkin null; jika referensi obyek Anda memiliki (yaitu 'ditarik') adalah pada kenyataannya null, itu tidak menunjuk ke sebuah obyek di heap. Ini berarti tidak ada objek di heap tempat panggilan untuk equals()berhasil.

Semoga berhasil!

outofcoffee
sumber
4
Saya juga lebih suka konstruksi if (<constant> == <variable>) sebagai cara untuk melindungi diri saya dari tugas yang tidak disengaja.
Scott
7

DIY

private boolean isNull(Object obj) {
    return obj == null;
}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (isNull(drawable)) {
    drawable = getRandomDrawable();
}
Eddie B
sumber
6
drawable.equals(null)

Baris di atas memanggil metode "sama dengan (...)" pada objek drawable.

Jadi, jika drawable bukan null dan merupakan objek nyata, semua berjalan baik dengan memanggil metode "sama dengan (null)" akan mengembalikan "salah"

Namun jika "drawable" bernilai null, artinya memanggil metode "sama dengan (...)" pada objek null, artinya memanggil metode pada objek yang tidak ada sehingga memunculkan "NullPointerException"

Untuk memeriksa apakah sebuah objek ada dan bukan null, gunakan yang berikut ini

if(drawable == null) {
    ...
    ...
}

Dalam kondisi di atas, kami memeriksa bahwa variabel referensi "drawable" adalah null atau berisi beberapa nilai (referensi ke objeknya) sehingga tidak akan memunculkan pengecualian jika drawable bernilai null karena memeriksa

null == null

adalah benar.

Yatendra Goel
sumber
5

if (yourObject instanceof yourClassName)akan mengevaluasi falsejika yourObjectada null.

heapuser
sumber
0

Mungkin sedikit lebih efisien untuk menangkap NullPointerException. Metode di atas berarti bahwa runtime memeriksa pointer nol dua kali.

Untuk Tuan
sumber
1
Di mana if x == nullsolusi check-in ganda ?
deamon
Setelah pernyataan if, runtime akan memeriksa lagi untuk pointer nol ketika objek digunakan. Saya tidak tahu apakah ini dioptimalkan oleh kompiler atau tidak.
Tom R
4
Ini bertentangan dengan kebijaksanaan konvensional, menggunakan pengecualian sebagai aliran kontrol.
Yakobus
1
Pengecualian sangat mahal, karena mereka perlu membuat pelacakan tumpukan secara keseluruhan.
deamon
0

Gunakan google guava libs untuk menangani is-null-check (pembaruan deamon)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());
Bala
sumber
Lebih baik gunakan Java 8 Optionalhari ini.
deamon
-1

Hanya untuk memberikan beberapa ide kepada pengembang sumber oracle Java :-)

Solusinya sudah ada di .Net dan lebih mudah dibaca!

Dalam Visual Basic .Net

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

Dalam C #

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

Solusi ini sangat efektif sebagai solusi Java Opsional (string default hanya dievaluasi jika nilai asli adalah null) tanpa menggunakan ekspresi lambda, hanya dengan menambahkan operator baru.

Hanya untuk melihat dengan cepat perbedaan dengan solusi Java, saya telah menambahkan 2 solusi Java

Menggunakan Opsional di Java

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Menggunakan {} di Java

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

Secara pribadi, saya suka VB.Net tetapi saya lebih suka ?? C#atau if {}solusi di Java ... dan Anda?

schlebe
sumber