开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
问题描述
java中String如果为null时,会在用+拼接时转换为字符串“null”。 如下面的例子:
public class StringTest {
public static void main(String[] args) {
String s1 = "s1";
String s2 = null;
String s3 = "s3";
System.out.println(s1+s2+s3);
}
}
输出的结果为:
s1nulls3
原因分析
为什么会将null对象转换成“null”字符串呢?
编译器对字符串相加会进行优化,首先实例化一个StringBuilder,然后把相加的字符串按顺序append,最后调用toString返回一个String对象。
StringBuilder源码如下
//针对 String 对象
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;
}
//针对非 String 对象
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
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;
}
可以看出StringBuilder.append函数如果判断String类型对象为 null,就会调用appendNull,填充”null”。
其他说明
java中System.out.println打印字符串时如果字符串为null也会答应为“null字符串”,源码如下:
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
java中System.out.println打印非String类型对象时通过调用String.valueOf方法,如果是 null 对象,就返回”null”,否则调用对象的toString方法。源码如下:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
《Thinking in Java》书中节选
Primitives that are fields in a class are automatically initialized to zero, as noted in the Everything Is an Object chapter. But the object references are initialized to null, and if you try to call methods for any of them, you’ll get an exception-a runtime error. Conveniently, you can still print a null reference without throwing an exception. 原生类型会被自动初始化为 0,但是对象引用会被初始化为 null,如果你尝试调用该对象的方法,就会抛出空指针异常。通常,你可以打印一个 null 对象而不会抛出异常。