看下面的程序和输出结果:
代码:
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb);
System.out.println(sb.length());
StringBuffer sb1 = new StringBuffer(str);
System.out.println(sb1);
输出结果:
null
4
Exception in thread "main" java.lang.NullPointerException
at java.lang.StringBuffer.<init>(StringBuffer.java:139)
at Test.main(Test.java:17)
这是为什么呢,我们来分析一下:
我们先来分析一下前两行的输出:
null
4
str对象是null,
但从输出来看sb并不是null,而是长度为4的字符串,这四个字符保存着正是字符串"null".
我们来可看一下append的底层代码:
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
================================================
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;
}
- StringBuffer append函数中的str仍然为null,然后传给AbstractStringBuilder append
- AbstractStringBuilder append 中判断str为null,然后调用AbstractStringBuilder appendNull
- AbstractStringBuilder appendNull 中把字符串"null"赋给保存数据的value,然后设置长度.所以输出的
null
4
我们再来分析那个异常
上面既然append,能把null对象保存为字符串"null",为什么当用null对象new 一个StringBuffer对象是会发生异常呢,我们还是来看底层代码:
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
通过异常信息,发生异常就是代码"super(str.length() + 16);",
这里传进来的str是null,而str.length()相当于null.length(),因此发生了异常