1. 程式人生 > >null物件列印為什麼是null?

null物件列印為什麼是null?

JAVA中有八種基本資料型別,他們在初始化的時候會被賦予初始值。

byte -> 0
short -> 0
int -> 0
long -> 0
char -> " "(看起來像是一個空格)
float -> 0.0
double -> 0.0
boolean -> false

引用型別物件初始化會被賦予初始值:null

String s = null;
try{
    s.toString();
} catch(NullPointerException e){
    e.printStackTrace();
}
System.out.println(s);

執行結果如下:

java.lang.NullPointerException
	at GjcTest.main(GjcTest.java:5)
null

問題1:String型別null物件為什麼會被列印成null?

當我們呼叫null物件的方法時,會丟擲異常。但是我們列印null物件卻不會丟擲異常,感覺是println方法對null物件做了什麼處理。

println方法原始碼如下:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

嗯,答案可能在方法print中,我們開啟print方法原始碼:

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

嗯,簡單粗暴的處理方式,如果傳入String物件是null,則直接列印字串“null”。

那如果是引用型別呢?我們就以Integer類作為示例。

Integer i = null;
try{
    i.toString();
} catch(NullPointerException e){
    e.printStackTrace();
}
System.out.println(i);

 執行結果如下:

java.lang.NullPointerException
	at GjcTest.main(GjcTest.java:5)
null

問題2:非String型別null物件為什麼會被列印成null?

我們先看一下println原始碼:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

 第一感覺是print方法應該是對null物件進行了處理的,我們直接開啟print方法原始碼:

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

嗯?怎麼呼叫的是引數型別是String型別的方法?哦,原來在println方法中,呼叫print方法引數型別是String類的,那麼問題應該是在println原始碼中第2行valueOf方法中。valueOf方法原始碼如下:

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

這個問題就解決了,如果傳入的引用型別物件是null,那麼返回字串“null”,否則呼叫物件的toString方法。

總結

String型別null物件處理方式:判斷物件是否是null,如果是null,列印字串“null”;如果不是null,列印字串。

非String型別null物件處理方式:判斷物件是否是null,如果是null,列印字串“null”;如果不是null,呼叫物件的toString方法,並列印字串。

我的疑問

高敬超

 如圖所示:println(Object o)處理邏輯是呼叫String.valueOf()方法,判斷物件o是否為空並返回需要列印的字串,然後呼叫print(String s)打印出來。為什麼println(Object o)不直接呼叫print(Object o)呢,程式碼如下。是設計者就是這樣設計的,還是有什麼原因?

public void println(Object x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}