前言
辞职休息了一个月,去了一次泰国,也疯够了。于是回来专心找工作。陆续去了一些公司参与面试,做了一些笔试题。有一道笔试题,我做错了。出乎我自己的意外。于是记录以吸取教训。
问题描叙
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
网友评论