Saya memiliki kode ini:
package tests;
import java.util.Hashtable;
public class Tests {
public static void main(String[] args) {
Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();
System.out.println("TEST 1");
System.out.println(modifiedItems.get("item1")); // Prints null
System.out.println("TEST 2");
System.out.println(modifiedItems.get("item1") == null); // Prints true
System.out.println("TEST 3");
System.out.println(Boolean.valueOf(null)); // Prints false
System.out.println("TEST 4");
System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
System.out.println("FINISHED!"); // Never executed
}
}
Masalah saya adalah saya tidak mengerti mengapa Tes 3 berfungsi dengan baik (mencetak false
dan tidak menghasilkan NullPointerException
) sementara Tes 4 melempar NullPointerException
. Seperti yang Anda lihat dalam tes 1 dan 2 , null
dan modifiedItems.get("item1")
adalah sama dengan dan null
.
Perilakunya sama di Java 7 dan 8.
java
nullpointerexception
boolean
David E
sumber
sumber
null
ke fungsi yang sama tidak menghasilkan NPE! Ada alasan bagus untuk itu, tapi itu pasti membingungkan pada pandangan pertama :-)==
penerapannya.Jawaban:
Anda harus melihat dengan cermat overload mana yang dipanggil:
Boolean.valueOf(null)
sedang memohonBoolean.valueOf(String)
. Ini tidak memunculkanNPE
bahkan jika disediakan dengan parameter null.Boolean.valueOf(modifiedItems.get("item1"))
dipanggilBoolean.valueOf(boolean)
, karenamodifiedItems
nilainya bertipeBoolean
, yang memerlukan konversi unboxing. KarenamodifiedItems.get("item1")
itunull
, unboxing dari nilai itu - bukanBoolean.valueOf(...)
- yang melempar NPE.Aturan untuk menentukan kelebihan beban yang dipanggil cukup rumit , tetapi secara kasar aturannya seperti ini:
Dalam lintasan pertama, metode yang cocok dicari tanpa mengizinkan tinju / unboxing (atau metode arity variabel).
null
adalah nilai yang dapat diterima untuk aString
tetapi tidakboolean
,Boolean.valueOf(null)
dicocokkan denganBoolean.valueOf(String)
dalam umpan ini;Boolean
tidak dapat diterima untuk salah satuBoolean.valueOf(String)
atauBoolean.valueOf(boolean)
, jadi tidak ada metode yang cocok untuk pass iniBoolean.valueOf(modifiedItems.get("item1"))
.Dalam lintasan kedua, metode yang cocok dicari, memungkinkan tinju / unboxing (tetapi masih bukan metode arity variabel).
Boolean
bisa di-unboxboolean
, jadiBoolean.valueOf(boolean)
cocok untukBoolean.valueOf(modifiedItems.get("item1"))
di pass ini; tetapi konversi unboxing harus disisipkan oleh compiler untuk memanggilnya:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
(Ada lintasan ketiga yang memungkinkan metode arity variabel, tetapi itu tidak relevan di sini, karena dua lintasan pertama cocok dengan kasus ini)
sumber
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
dalam kode sumber daripadaBoolean.valueOf(modifiedItems.get("item1"))
?.booleanValue()
terkubur dalam ekspresi. Dua pengamatan: 1) auto (un) boxing adalah fitur Java yang disengaja untuk menghilangkan celah sintaksis; melakukannya sendiri adalah mungkin, tetapi tidak idiomatis; 2) ini tidak membantu Anda sama sekali - ini tentu saja tidak menghentikan terjadinya masalah, juga tidak memberikan info tambahan saat kegagalan terjadi (jejak tumpukan akan identik, karena kode yang dieksekusi identik).Karena
modifiedItems.get
mengembalikan aBoolean
(yang tidak dapat di- cast ke aString
), tanda tangan yang akan digunakan adalahBoolean.valueOf(boolean)
, di manaBoolean
outboxnya menjadi primitifboolean
. Setelahnull
dikembalikan sana, outboxing gagal denganNullPointerException
.sumber
Tanda tangan metode
Metode ini
Boolean.valueOf(...)
memiliki dua tanda tangan:public static Boolean valueOf(boolean b)
public static Boolean valueOf(String s)
modifiedItems
Nilai Anda adalahBoolean
. Anda tidak dapat melemparkanBoolean
keString
sehingga akibatnya tanda tangan pertama akan dipilihUnboxing Boolean
Dalam pernyataan Anda
yang bisa dibaca sebagai
Namun, pada dasarnya
modifiedItems.get("item1")
kembalinull
jadi Anda akan memilikinyayang jelas mengarah ke a
NullPointerException
sumber
Seperti yang sudah dijelaskan Andy dengan sangat baik alasan dari
NullPointerException
:yang disebabkan oleh Boolean un-boxing:
diubah menjadi:
saat runtime dan kemudian membuang
NullPointerException
jikamodifiedItems.get("item1")
null.Sekarang saya ingin menambahkan satu poin lagi di sini bahwa un-boxing dari kelas-kelas berikut ke primitif masing-masing juga dapat menghasilkan
NullPointerException
pengecualian jika objek yang dikembalikan sesuai nol.Ini kodenya:
sumber
Sebuah cara untuk memahaminya adalah ketika
Boolean.valueOf(null)
dipanggil, java dengan tepat diberitahu untuk mengevaluasi null.Namun, ketika
Boolean.valueOf(modifiedItems.get("item1"))
dipanggil, java diberitahu untuk mendapatkan nilai dari HashTable tipe objek Boolean, tetapi ia tidak menemukan tipe Boolean, ia malah menemukan jalan buntu (null) meskipun ia mengharapkan Boolean. Pengecualian NullPointerException dilemparkan karena pembuat bagian java ini memutuskan bahwa situasi ini adalah contoh dari sesuatu yang salah dalam program yang memerlukan perhatian programmer. (Sesuatu yang tidak diinginkan terjadi.)Dalam hal ini lebih banyak perbedaan antara sengaja menyatakan bahwa Anda menginginkan null ada di sana, dan java menemukan referensi yang hilang ke objek (null) di mana objek itu dimaksudkan untuk ditemukan.
Lihat informasi selengkapnya tentang NullPointerException di jawaban ini: https://stackoverflow.com/a/25721181/4425643
sumber