Java'da null ile döküm yaparken istisna yok


227
String x = (String) null;

Bu ifadede neden bir istisna yoktur?

String x = null;
System.out.println(x);

Yazdırır null. Ancak .toString()yöntem, boş bir işaretçi istisnası atmalıdır.


ne istisna hakkında konuşuyorsun, derleyici?
Sajan Chandran

Yanıtlar:


323

nullHerhangi bir istisna almadan herhangi bir referans türüne başvurabilirsiniz .

printlnNesne denetler boş olup olmadığını, çünkü yöntem boş gösterici atmak değildir. Null ise, dizeyi basar "null". Aksi takdirde toString, o nesnenin yöntemini çağıracaktır .

Daha fazla ayrıntı ekleme: Dahili yazdırma yöntemleri String.valueOf(object), giriş nesnesindeki yöntemi çağırır . Ve valueOfyöntemde, bu kontrol boş işaretçi istisnasını önlemeye yardımcı olur:

return (obj == null) ? "null" : obj.toString();

Karışıklığınızın geri kalanı için, boş bir nesnede herhangi bir yöntemi çağırmak, özel bir durum olmasa bile boş bir işaretçi istisnası atmalıdır.


1
@JunedAhsan hangi özel durumlar NPE atmamasına neden olur?
Holloway

@Trengot Aşağıdaki Peter yanıtında bahsedilenlerden birini kontrol edin.
Junsan Ahsan

144

nullHerhangi bir referans türüne yayın yapabilirsiniz . Ayrıca a öğesini nullbağımsız değişken olarak işleyen yöntemleri de çağırabilirsiniz , örn. System.out.println(Object)Yapar, ancak bir nulldeğere başvuramaz ve bu yöntemi çağıramazsınız.

BTW nullDeğerler üzerinde statik yöntemler çağırabileceğiniz zor bir durum var .

Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.

12
Vay. Sorulursa, bir istisna atacağından% 100 emin olabilirim. Gerçekten zor bir dava.
Magnilex

2
@Magnilex: Kesinlikle! Bu tipik bir OCPJP sınavı hile sorusudur.
ccpizza

3
Bayt kodundaki derleyici bunu t.yield() -> Thread.yeld() zaten "optimize ettiği" için değil mi? Nasıl final int i = 1; while (i == 1)optimize edilirwhile(true)
SGal

@SGal Daha da iyisi çünkü ilk optimizasyonda ikinci optimizasyon AFAIK zorunlu değil.
Paul Stelian

36

Bu tasarım gereğidir. nullHerhangi bir referans türüne yayın yapabilirsiniz . Aksi takdirde referans değişkenlere atayamazsınız.


Teşekkürler! referans değişkenlere null atanmasıyla ilgili bu not gerçekten yararlıdır!
Max

22

Bir yöntemin aşırı yüklendiği ve aşağıdaki aşırı yük yöntemlerine null iletildiği zaman aşağıdaki yapı için döküm null değerleri gereklidir, bu durumda derleyici belirsizliği nasıl temizleyeceğini bilmez, bu nedenle bu durumlarda null yazmamız gerekir:

class A {
  public void foo(Long l) {
    // do something with l
  }
  public void foo(String s) {
    // do something with s      
  }
}
new A().foo((String)null);
new A().foo((Long)null);

Aksi takdirde, ihtiyacınız olan yöntemi çağıramazsınız.


Çoğu durumda, döküm örtüktür, örneğin değeri değerine String bar = null;çevirir . Şimdiye kadar sadece bir yöntemin aşırı yüklendiği bir testte açıkça null kullanmak zorunda kaldım ve davranışını null girdi ile test etmek istedim. Yine de, seninkini bulmadan önce benzer bir cevap yazmak üzereydim. nullString
Vlasec

Eğlenceli gerçek: l instanceof Longve bu durumlarda s instanceof Stringgeri dönecektir false.
Attila Tanyi

7

Println(Object) kullanımları String.valueOf()

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Print(String) null denetimi yapar.

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}


3

Diğerlerinin yazdığı gibi, her şeye null değer atabilirsiniz. Normalde buna ihtiyacınız olmaz, şunları yazabilirsiniz:

String nullString = null;

oyuncuları oraya koymadan.

Ancak bu tür yayınların mantıklı olduğu durumlar vardır:

a) Aşağıdaki gibi belirli bir yöntemin çağrıldığından emin olmak istiyorsanız:

void foo(String bar) {  ... }
void foo(Object bar) {  ... }

o zaman yazarsanız bir fark yaratır

foo((String) null) vs. foo(null)

b) IDE'nizi kod üretmek için kullanmayı düşünüyorsanız; Örneğin ben genellikle gibi birim testleri yazıyorum:

@Test(expected=NullPointerException.class)
public testCtorWithNullWhatever() {
    new MyClassUnderTest((Whatever) null);
}

TDD yapıyorum; Bu, "MyClassUnderTest" sınıfının muhtemelen henüz mevcut olmadığı anlamına gelir. Bu kodu yazarak, sonra yeni sınıf oluşturmak için benim IDE kullanabilirsiniz; ve daha sonra "kutudan" ne olursa olsun "argümanını" kabul eden bir kurucu oluşturmak için - IDE testimden kurucunun Whatever türünde tam bir argüman alması gerektiğini anlayabilir.


2

Yazdır :

Bir nesneyi yazdırın. String.valueOf (Object) yöntemi tarafından üretilen dize bayta çevrilir

Değer :

bağımsız değişken null olursa, "null" değerine eşit bir dize; aksi takdirde obj.toString () değeri döndürülür.

Nesne olduğunda "null" değerine sahip bir dize döndürür null.


2

Bu, aksi takdirde belirsiz olabilecek bir yöntem kullanırken çok kullanışlıdır. Örneğin: JDialog, aşağıdaki imzalara sahip kuruculara sahiptir:

JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Dialog, String, boolean, GraphicsConfiguration)

GraphicsConfiguration ayarlamak istiyorum, ancak bu iletişim kutusu için üst var, bu nedenle ilk bağımsız değişken boş olmalıdır, çünkü bu yapıcı kullanmanız gerekir. kullanma

JDialog(null, String, boolean, Graphicsconfiguration) 

belirsiz olduğundan, bu durumda desteklenen türlerden birine null değer atayarak aramayı daraltabilirim:

JDialog((Frame) null, String, boolean, GraphicsConfiguration)

0

Bu dil özelliği bu durumda kullanışlıdır.

public String getName() {
  return (String) memberHashMap.get("Name");
}

MemberHashMap.get ("Name") null değerini döndürürse, yukarıdaki yöntemin istisna atmadan null değerini döndürmesini istersiniz. Sınıf ne olursa olsun null boştur.

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.