String.valueOf (null) neden bir NullPointerException oluşturur?


127

belgelere göre, yöntem şunu String.valueOf(Object obj)döndürür:

argüman ise null, o zaman bir dizge eşittir "null"; aksi takdirde değeri obj.toString()döndürülür.

Ama bunu yapmayı denediğimde nasıl oluyor?

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

onun yerine NPE atar? (inanmıyorsanız kendiniz deneyin!)

    "Main" iş parçacığında istisna java.lang.NullPointerException
    java.lang.String. (Bilinmeyen Kaynak)
    java.lang.String.valueOf (Bilinmeyen Kaynak) at

Bu nasıl oluyor? Belgeler bana yalan mı söylüyor? Bu Java'da büyük bir hata mı?

Yanıtlar:


201

Sorun, String.valueOfyöntemin aşırı yüklenmesi :

Java Spesifikasyon Dili, bu tür durumlarda, en spesifik aşırı yüklemenin seçilmesini zorunlu kılar :

JLS 15.12.2.5 En Özel Yöntemi Seçme

Birden fazla üye yöntemin hem erişilebilir hem de bir yöntem çağrısı için geçerli olması durumunda, çalıştırma zamanı yöntemi gönderimi için tanımlayıcı sağlamak üzere birini seçmek gerekir. Java programlama dili, en özel yöntemin seçildiği kuralı kullanır .

A char[] eşittir Object , ancak hepsi Object bir değildir char[] . Bu nedenle, char[]bir daha spesifik daha Objectve Java dili tarafından belirtildiği gibi, String.valueOf(char[])aşırı yük bu durumda seçilir.

String.valueOf(char[])Dizi olmayan olmasını bekler nullve o zamandan beri null, bu durumda verilir, daha sonra atar NullPointerException.

Kolay "düzeltme", bunu nullaçıkça Objectaşağıdaki gibi yapmaktır:

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

İlgili sorular


Hikayeden çıkarılacak ders

Birkaç önemli nokta var:

  • Etkili Java 2. Sürüm, Madde 41: Aşırı yüklemeyi mantıklı kullanın
    • Aşırı yükleyebildiğin için her seferinde yapman gerektiği anlamına gelmez
    • Kafa karışıklığına neden olabilirler (özellikle yöntemler çılgınca farklı şeyler yapıyorsa)
  • İyi bir IDE kullanarak, derleme zamanında hangi aşırı yüklemenin seçildiğini kontrol edebilirsiniz.
    • Eclipse ile, yukarıdaki ifadeye fare hover can ve görüyoruz aslında , valueOf(char[])aşırı yük seçilir!
  • Bazen açıkça nullyayınlamak istersiniz (takip edilecek örnekler)

Ayrıca bakınız


Dökümde null

nullBelirli bir referans türüne açıkça atamanın gerekli olduğu en az iki durum vardır :

  • Aşırı yüklemeyi seçmek için (yukarıdaki örnekte verildiği gibi)
  • Vermek nullbir vararg parametresine tek bir argüman olarak

İkincisinin basit bir örneği şudur:

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

O zaman aşağıdakilere sahip olabiliriz:

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

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

Ayrıca bakınız

İlgili sorular


5
Başka bir öneri: Bir yöntemi aşırı yüklediğinizde ve bir bağımsız değişken iki aşırı yüklemede çağrılabilir ( nullbu durumda olduğu gibi ), her iki aşırı yüklemenin bu değer açısından aynı şekilde davrandığından emin olun!
Joachim Sauer

3
@ Joachim: Maddeyi yeni okudum ve bu iki yöntemin açıkça tartışıldığını görünce çok şaşırdım! Bloch bir adım daha ileri gitti ve o zamandan beri String.valueOf(Object)ve valueOf(char[])her halükarda tamamen farklı şeyler yaptığını (ne olursa olsun nullya da olmasın), belki de ilk etapta aşırı yük olmamaları gerektiğini iddia ediyor.
poligenel yağlayıcılar

Bir sorunuz var ... Bir Object döndüren bir yönteminiz varsa, o zaman ifade ile return null;aynı şey olur return (Object) null;mu?
user972276

17

Sorun, aramanız String.valueOf(char[])ve değil String.valueOf(Object) .

Bunun nedeni, Java'nın her zaman aşırı yüklenmiş bir yöntemin sağlanan parametrelerle çalışan en spesifik sürümünü seçmesidir. nullbir Objectparametre için geçerli bir değerdir , ancak aynı zamanda bir char[]parametre için de geçerli bir değerdir .

Java'nın Objectsürümü kullanmasını sağlamak için , nullbir değişken aracılığıyla iletin veya Object'e açık bir atama belirtin:

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

5

2003 yılında bu yol için 4867608 numaralı bir hata dosyalanmış ve bu açıklama ile "düzeltilmez" olarak çözülmüştür.

Uyumluluk kısıtlamaları nedeniyle bunu değiştiremeyiz. Bunun çağrılmaya son veren genel statik String valueOf (char data []) yöntemi olduğunu ve boş argümanlar için "null" değiştirilmesinden bahsetmediğini unutmayın.

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


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.