"hello"+null = ? 关于String拼接null字符的问题
前言
昨天在做笔试题的时候遇到了一个之前没有遇见过的问题,所以特地记录下来。题目是这样的:
String s1 = null;
String s2 = s1 + "hello";
System.out.println(s2);
//求上述s2的打印结果
我一开始认为既然s1是null,那不就说明s1什么都没有,那将它拼接到s2上去肯定结果还是"hello",于是想也没有想就直接选择了这个答案(PS:没看过String源码呀,所以完全不会o(╥﹏╥)o),最后在IDEA上进行验证果然给我好好上了一课。结果当然是nullhello。后来好奇在网上查找了有关技术文章才大致明白为什么会将null也作为一个字符串拼接上去。
提示:以下是本篇文章正文内容,下面案例可供参考
一、String的拼接操作: ‘’+‘’?
我们知道在String中有一个拼接操作,它的作用是将两个字符串进行拼接形成一个新的字符串。因为String是一个类,而"+“是String类中的一个操作。在Java中我们知道类中所有的"操作"都应该对应于一个方法。那么”+"对应哪个方法呢?不难发现当有变量参与字符串的拼接操作时,String会借用StringBuilder对象的append()方法来完成(JDK1.5之前借用StringBuffer)。
所以为了一探究竟,我们可以看一下append()方法的源码。
二、看源码
append()在JDK中的源码如下
代码如下(示例):
public StringBuilder append(String str) {
super.append(str);
return this;
}
这里我们发现它调用了父类的append()方法,那么它的父类又是哪个类呢?
通过查找发现有一个关系是StringBuffer、StringBuilder、String 对 CharSequence 接口的实现过程不一样,CharSequence 是一个定义字符串操作的接口,它只包括 length()、charAt(int index)、subSequence(int start, int end) 这几个 API。如下图所示:
在这里我们就不难发现String 是直接实现了 CharSequence 接口,而StringBuilder 和 StringBuffer 都是可变的字符序列,它们都继承于 AbstractStringBuilder,实现了 CharSequence 接口。所以显然super.append()调用的是父类AbstractStringBuilder中的append(),父类中append()的源码如下:
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
ensureCapacityInternal(count + len);
putStringAt(count, str);
count += len;
return this;
}
从源码可知,当拼接null时,会调用appendNull()方法,其源码如下:
private AbstractStringBuilder appendNull() {
ensureCapacityInternal(count + 4);
int count = this.count;
byte[] val = this.value;
if (isLatin1()) {
val[count++] = 'n';
val[count++] = 'u';
val[count++] = 'l';
val[count++] = 'l';
} else {
count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
}
this.count = count;
return this;
}
到这里我们就大致明白了当传入的字符串为null时,会调用appendNull()方法生成一个字符数组char[],并自动给这个字符数组拼接上’n’,‘u’,‘l’,'l’四个字符。所以最后s1的返回结果是字符串"null"。
总结
综上,本文重点是:String的"+"会调用StringBuilder的append()方法,然后顺着调用关系往下查阅源码即可知答案。