Mengapa String.valueOf (null) melempar NullPointerException?

127

menurut dokumentasi, metode String.valueOf(Object obj)mengembalikan:

jika argumennya adalah null, maka string sama dengan "null"; jika tidak, nilai obj.toString()dikembalikan.

Tetapi bagaimana bisa ketika saya mencoba melakukan ini:

System.out.println("String.valueOf(null) = " + String.valueOf(null));

itu melempar NPE saja? (coba sendiri jika Anda tidak percaya!)

    Pengecualian di utas "utama" java.lang.NullPointerException
    di java.lang.String. (Sumber Tidak Dikenal)
    di java.lang.String.valueOf (Sumber Tidak Dikenal)

Kenapa ini terjadi? Apakah dokumentasi itu bohong padaku? Apakah ini bug utama di Jawa?

pengguna282886
sumber

Jawaban:

201

Masalahnya adalah bahwa String.valueOfmetode kelebihan beban :

Java Spesifikasi Bahasa mengamanatkan bahwa dalam kasus-kasus semacam ini, kelebihan yang paling spesifik dipilih:

JLS 15.12.2.5 Memilih Metode Paling Spesifik

Jika lebih dari satu metode anggota dapat diakses dan berlaku untuk pemanggilan metode, perlu memilih satu untuk memberikan deskriptor untuk pengiriman metode run-time. Bahasa pemrograman Java menggunakan aturan bahwa metode yang paling spesifik dipilih.

A char[] adalah-an Object , tetapi tidak semua Object is-a char[] . Oleh karena itu, char[]adalah lebih spesifik dari Object, dan seperti yang ditentukan oleh bahasa Jawa, String.valueOf(char[])kelebihan dipilih dalam kasus ini.

String.valueOf(char[])mengharapkan array menjadi non- null, dan karena nulldiberikan dalam kasus ini, ia kemudian melempar NullPointerException.

"Perbaikan" yang mudah adalah dengan melemparkan nullsecara eksplisit ke Objectsebagai berikut:

System.out.println(String.valueOf((Object) null));
// prints "null"

Pertanyaan-pertanyaan Terkait


Pesan moral dalam cerita

Ada beberapa yang penting:

  • Java Edisi 2 yang Efektif, Butir 41: Gunakan kelebihan muatan dengan bijaksana
    • Hanya karena Anda bisa kelebihan, bukan berarti Anda harus setiap saat
    • Mereka dapat menyebabkan kebingungan (terutama jika metode melakukan hal-hal yang sangat berbeda)
  • Menggunakan IDE yang baik, Anda dapat memeriksa kelebihan beban yang dipilih pada waktu kompilasi
    • Dengan Eclipse, Anda dapat mengarahkan mouse ke ekspresi di atas dan melihat memang , valueOf(char[])kelebihan dipilih!
  • Terkadang Anda ingin memberikan secara eksplisit null(contoh untuk diikuti)

Lihat juga


Saat casting null

Setidaknya ada dua situasi di mana secara eksplisit casting nullke tipe referensi tertentu diperlukan:

  • Untuk memilih kelebihan beban (seperti yang diberikan dalam contoh di atas)
  • Untuk memberikan nullsebagai argumen tunggal ke parameter vararg

Contoh sederhana dari yang terakhir adalah sebagai berikut:

static void vararg(Object... os) {
    System.out.println(os.length);
}

Kemudian, kita dapat memiliki yang berikut ini:

vararg(null, null, null); // prints "3"
vararg(null, null);       // prints "2"
vararg(null);             // throws NullPointerException!

vararg((Object) null);    // prints "1"

Lihat juga

Pertanyaan-pertanyaan Terkait

polygenelubricants
sumber
5
Saran lain: Ketika Anda membebani suatu metode dan satu argumen dapat dipanggil pada dua kelebihan (seperti nulldalam kasus ini), pastikan bahwa kedua kelebihan tersebut bertindak sama terkait dengan nilai itu!
Joachim Sauer
3
@ Joachim: Saya baru saja membaca item itu, dan terkejut menemukan bahwa kedua metode ini dibahas secara eksplisit! Bloch melangkah lebih jauh dan mengklaim bahwa sejak String.valueOf(Object)dan valueOf(char[])melakukan hal-hal yang sama sekali berbeda (terlepas dari nullatau tidak) bahwa mungkin mereka seharusnya tidak kelebihan beban di tempat pertama.
polygenelubricants
Punya pertanyaan ... jika Anda memiliki metode yang mengembalikan Objek maka pernyataannya return null;akan sama persis dengan return (Object) null;?
user972276
17

Masalahnya adalah Anda menelepon String.valueOf(char[])dan tidak String.valueOf(Object) .

Alasannya adalah bahwa Java akan selalu memilih versi paling spesifik dari metode kelebihan beban yang bekerja dengan parameter yang disediakan. nulladalah nilai yang valid untuk suatu Objectparameter, tetapi juga nilai yang valid untuk suatu char[]parameter.

Untuk membuat Java menggunakan Objectversi, baik lewat nullvariabel atau tentukan gips eksplisit ke Object:

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));
Joachim Sauer
sumber
5

Bug, bernomor 4867608 diajukan dengan cara ini pada tahun 2003, yang diselesaikan sebagai "tidak akan diperbaiki" dengan penjelasan ini.

Kami tidak dapat mengubah ini karena kendala kompatibilitas. Perhatikan bahwa ini adalah metode String public valueOf (char data []) statis yang akhirnya dipanggil dan tidak menyebutkan penggantian "null" untuk argumen null.

@ ###. ### 2003-05-23

cbare
sumber
0

Gunakan String.valueOf(null: Any)di Scala.

Profiterol
sumber