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();
}
}