前言
辭職休息了一個月,去了一次泰國,也瘋夠了。于是回來專心找工作。陸續去了一些公司參與面試,做了一些筆試題。有一道筆試題,我做錯了。出乎我自己的意外。于是記錄以吸取教訓。
問題描敘
String s = null;
System.out.print("s="+s);
程序執行的結果是什么?是否會報錯?
我的回答(錯誤)
考慮s為null, 字符串連接的時候,我認為 會調用s的toString() 方法。這樣肯定出現空指針異常。
于是我寫出答案:
- 程序可以編譯,但是運行時報異常。空指針異常。
正確答案
s=null
這真是讓我很懵逼。居然可以執行。而且還是null 。
解決思路
這個問題可以拆分為三個小問題。
第一個問題
String s = null;
System.out.print(s);
結果輸出為 null ,這里為何輸出null .問題出在 pring函數上。定位該函數的源碼,其中有這樣的一段。
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
很粗暴的判斷。jdk的簡單處理,有點讓人失望。
第二個問題。
Integer i = null;
System.out.print(i);
結果輸出是null. 查看函數源碼
public void print(Object obj) {
write(String.valueOf(obj));
}
繼續
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
一切真相大白。
第三個問題。
就是我們的面試題目,這里也是相同的原因嗎?
由于 + 是基本運算符,我們無法直接查看源碼,了解其執行的邏輯。
這個只能去查詢資料。最終的結論是 jvm 會對 + 進行優化。其執行邏輯如下:
String s = "a" + "b";
//等價于
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
String s = sb.toString();
因此 我們只需要去查看 append即可。
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
結果很明顯。字符串執行 + 時,如果字符串為Null 最終添加的是 null 字符串。
總結
-
print函數對null的處理。
- String 對象:直接判斷是否為 null,如果為 null 給 null 對象賦值為"null"。
- 非 String 對象:通過調用String.valueOf方法,如果是 null 對象,就返回"null",否則調用對象的toString方法。
-
字符串相加( +) 對null的處理
- jvm會將+ 優化為 StringBuilder來處理。如果為null 則添加 "null"
以上2點,最終的結果是
打印一個 null 對象而不會拋出異常
至于為何要如此,不知道jdk的作者是怎么想的。
參考
感謝 http://blog.xiaohansong.com/2016/03/13/null-in-java-string/
其他類似面試題
類似這類的面試題還有。例如
Integer a = 12;
Integer b = 12;
System.out.println(a == b);
Integer a = new Integer(12);
Integer b = new Integer(12);
System.out.println(a == b);
Integer a = 212;
Integer b = 212;
System.out.println(a == b);
Integer a = 212;
int b = 212;
System.out.println(a == b);
以上分別打印什么? 能正確回答的估計寥寥無幾。
答案與分析http://m.blog.csdn.net/csummm4/article/details/20659363