最近和同事讨论了下面的一段代码:
String a = null; a += a; System.out.println(a);
运行结果:
nullnull
本着学习的态度研究了一下这段代码,在本地将上面代码编写之后使用javap反编译Java字节码文件得到下面字节命令:
Code: 0: aconst_null 1: astore_1 2: new #16 // class java/lang/StringBuilder 5: dup 6: aload_1 7: invokestatic #18 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 10: invokespecial #24 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 13: aload_1 14: invokevirtual #27 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: invokevirtual #31 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 20: astore_1 21: getstatic #35 // Field java/lang/System.out:Ljava/io/PrintStream; 24: aload_1 25: invokevirtual #41 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 28: return
原来编译器对字符串相加会进行优化,首先创建一个StringBuilder对象,然后把相加的字符串按顺序append,最后调用toString方法返回一个String对象。
还是看一下源码StringBuilder的append方法是如何处理null的吧。
public StringBuilder append(String str) { 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; }
append方法会判断传入对象如果为null,就会调用appendNull方法,appendNull方法填充了一个char[]数组,其内容为"null"。