Saya telah mencatat bahwa banyak metode Java 8 dalam penggunaan Oracle JDK Objects.requireNonNull()
, yang secara internal melempar NullPointerException
jika objek yang diberikan (argumen) null
.
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Namun NullPointerException
akan tetap terlempar pula jika suatu null
objek mengalami dereferensi. Jadi, mengapa orang harus melakukan pemeriksaan dan lemparan nol tambahan ini
NullPointerException
?
Satu jawaban yang jelas (atau manfaat) adalah membuat kode lebih mudah dibaca dan saya setuju. Saya ingin mengetahui alasan lain untuk menggunakan
Objects.requireNonNull()
di awal metode ini.
java
java-8
nullpointerexception
pengguna4686046
sumber
sumber
Objects.requireNonNull
, kode Anda tidak memiliki percabangan sehingga satu lulus uji unit akan memberi Anda cakupan 100% :-)Jawaban:
Karena Anda dapat membuat hal-hal eksplisit dengan melakukannya. Suka:
Atau lebih pendek:
Sekarang Anda tahu :
new()
Bandingkan dengan: Anda membuat objek Foo hari ini, dan besok Anda memanggil metode yang menggunakan bidang itu dan melempar. Kemungkinan besar, Anda tidak akan tahu besok mengapa referensi itu nol kemarin ketika diteruskan ke konstruktor!
Dengan kata lain: dengan menggunakan metode ini secara eksplisit untuk memeriksa referensi yang masuk Anda dapat mengontrol titik waktu ketika pengecualian akan dilemparkan. Dan sebagian besar waktu, Anda ingin gagal secepat mungkin !
Keuntungan utama adalah:
bar
bukan nol - dan dengan demikian Anda tidak memerlukanif (bar == null)
pemeriksaan di tempat lain!sumber
this.bar = Objects.requireNonNull(bar, "bar must not be null");
Objects.requireNonNull(bar, "bar must not be null");
. Terima kasih untuk yang satu ini.this.bar = Objects.requireNonNull(bar, "bar must not be null");
ok di konstruktor, tetapi berpotensi berbahaya dalam metode lain jika dua atau lebih variabel diatur dalam metode yang sama. Contoh: talkwards.com/2018/11/03/...Gagal cepat
Kode harus macet sesegera mungkin. Seharusnya tidak melakukan setengah dari pekerjaan dan kemudian membatalkan null dan crash hanya kemudian meninggalkan setengah dari beberapa pekerjaan yang dilakukan menyebabkan sistem berada dalam keadaan tidak valid.
Ini biasa disebut "gagal awal" atau "gagal cepat" .
sumber
Ini berarti Anda mendeteksi masalah dengan segera dan andal .
Mempertimbangkan:
.NET membuat ini lebih baik dengan memisahkan
NullReferenceException
("Anda mendefinisikan nilai nol") dariArgumentNullException
("Anda seharusnya tidak melewatkan nol sebagai argumen - dan itu untuk parameter ini ). Saya berharap Jawa melakukan hal yang sama, tetapi bahkan dengan hanya aNullPointerException
, itu masih jauh lebih mudah untuk memperbaiki kode jika kesalahan dilemparkan pada titik paling awal di mana ia dapat dideteksi.sumber
Menggunakan
requireNonNull()
sebagai pernyataan pertama dalam suatu metode memungkinkan untuk mengidentifikasi sekarang / puasa penyebab pengecualian.Stacktrace menunjukkan dengan jelas bahwa pengecualian dilemparkan segera setelah masuknya metode karena penelepon tidak menghormati persyaratan / kontrak. Melewati suatu
null
objek ke metode lain mungkin memang memprovokasi pengecualian pada suatu waktu, tetapi penyebab masalahnya mungkin lebih rumit untuk dipahami karena pengecualian akan dilemparkan dalam doa khusus padanull
objek yang mungkin jauh lebih jauh.Berikut ini adalah contoh nyata dan nyata yang menunjukkan mengapa kita harus memilih gagal cepat secara umum dan lebih khusus menggunakan
Object.requireNonNull()
atau cara apa pun untuk melakukan pemeriksaan tanpa nol pada parameter yang dirancang bukannull
.Misalkan
Dictionary
kelas yang membentuk suatuLookupService
danList
dariString
yang mewakili kata-kata yang terkandung dalam. Bidang ini dirancang untuk tidaknull
dan salah satu dari ini dilewatkan diDictionary
konstruktor.Sekarang anggaplah implementasi "buruk"
Dictionary
tanpanull
memeriksa entri metode (di sini adalah konstruktor):Sekarang, mari kita panggil
Dictionary
konstruktor dengannull
referensi untukwords
parameter:JVM melempar NPE pada pernyataan ini:
Pengecualian dipicu di
LookupService
kelas sementara asal usulnya jauh lebih awal (Dictionary
konstruktor). Itu membuat analisis masalah secara keseluruhan menjadi kurang jelas.Benarkah
words
null
? Benarkahwords.get(0) null
? Keduanya? Mengapa yang satu, yang lain atau mungkin keduanyanull
? Apakah ini merupakan kesalahan pengkodean dalamDictionary
(konstruktor? Metode yang dipanggil?)? Apakah ada kesalahan pengkodeanLookupService
? (konstruktor? metode yang dipanggil?)?Akhirnya, kita harus memeriksa lebih banyak kode untuk menemukan asal kesalahan dan dalam kelas yang lebih kompleks bahkan mungkin menggunakan debugger untuk lebih mudah memahami apa yang terjadi.
Tetapi mengapa hal sederhana (kurangnya cek nol) menjadi masalah yang kompleks? Bayangkan itu
Karena kami mengizinkan bug awal / kekurangan dapat diidentifikasi pada kebocoran komponen tertentu pada komponen yang lebih rendah.
LookupService
itu bukan layanan lokal tetapi layanan jarak jauh atau perpustakaan pihak ketiga dengan sedikit informasi debug atau bayangkan bahwa Anda tidak memiliki 2 lapisan tetapi 4 atau 5 lapisan objek doa sebelumnull
terdeteksi? Masalahnya akan lebih kompleks untuk dianalisis.Jadi cara untuk mendukung adalah:
Dengan cara ini, tidak ada sakit kepala: kami mendapatkan pengecualian yang dilemparkan segera setelah ini diterima:
Perhatikan bahwa di sini saya mengilustrasikan masalah dengan konstruktor tetapi pemanggilan metode dapat memiliki kendala periksa nihil yang sama.
sumber
Sebagai catatan, ini gagal cepat sebelum
Object#requireNotNull
diimplementasikan sedikit berbeda sebelum java-9 di dalam beberapa kelas jre sendiri. Misalkan kasus:Dalam java-8 ini dikompilasi sebagai (hanya bagian yang relevan)
Pada dasarnya operasi sebagai:
yourReference.getClass
- yang akan gagal jika referensi Andanull
.Banyak hal telah berubah di jdk-9 di mana kode yang sama dikompilasi
Atau pada dasarnya
Objects.requireNotNull (yourReference)
sumber
Penggunaan dasar adalah memeriksa dan melempar dengan
NullPointerException
segera.Salah satu alternatif (pintasan) yang lebih baik untuk memenuhi kebutuhan yang sama adalah penjelasan @NonNull oleh lombok.
sumber
Pengecualian null pointer dilemparkan ketika Anda mengakses anggota objek yang
null
pada titik kemudian.Objects.requireNonNull()
segera memeriksa nilai dan melempar pengecualian secara instan tanpa bergerak maju.sumber
Saya pikir itu harus digunakan dalam copy constructor dan beberapa kasus lain seperti DI yang parameter inputnya adalah objek, Anda harus memeriksa apakah parameternya nol. Dalam keadaan seperti itu, Anda dapat menggunakan metode statis ini dengan mudah.
sumber
Dalam konteks ekstensi kompiler yang menerapkan pemeriksaan Nullability (mis: uber / NullAway ),
Objects.requireNonNull
harus digunakan agak hemat untuk kesempatan ketika Anda memiliki bidang nullable yang kebetulan Anda ketahui bukan nol pada titik tertentu dalam kode Anda.Dengan cara ini, ada dua penggunaan utama:
Validasi
Penandaan nullability (berubah dari @Nullable ke @Nonnull)
Contoh penggunaan penandaan Nullability:
sumber
Selain semua jawaban yang benar:
Kami menggunakannya dalam aliran reaktif. Biasanya
NullpointerException
s yang dihasilkan dibungkus dengan Pengecualian lain tergantung pada kejadian mereka di sungai. Karenanya, nanti kita dapat dengan mudah memutuskan bagaimana menangani kesalahan.Contoh saja: Bayangkan Anda punya
di mana
parseAndValidate
wrappsNullPointerException
darirequireNonNull
dalamParsingException
.Sekarang Anda dapat memutuskan, misalnya kapan akan mencoba lagi atau tidak:
Tanpa pemeriksaan, NullPointerException akan terjadi dalam
save
metode, yang akan menghasilkan percobaan ulang tanpa akhir. Bahkan layak, bayangkan berlangganan lama, menambahkanSekarang
RetryExhaustException
langganan Anda akan terbunuh.sumber