Java String 遇上 +

遇到这样一段代码,运行发现结果出现意外。

String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";// @1
String str4 = "string";
System.out.println(str3 == str4);//true
String str5 = str1 + str2;// @2
System.out.println(str5 == str4);//false

代码虽然短,但是背后的知识点却是不少,涉及到常量池,运算符重载等相关知识点。
关于Java字符串拼接的知识可以参考:
http://droidyue.com/blog/2014/08/30/java-details-string-concatenation/
http://www.jianshu.com/p/88aa19fc21c6

使用java反编译命令javap -c Test可以看到编译优化后的代码


Paste_Image.png

此处主要分析关键2处,@1和@2

@1处,此处的拼接是在java编译阶段实现,由java编译器实现。直接把str和ing拼凑形成一个新的字符串常量报存在常量池中。所以str3 == str4输出true很好理解。
@2处,输出为什么会为false呢。这也是自己刚开始不明白的,看了编译后的代码终于明白。
String str5 = str1 + str2对应编译后代码30行,创建了一个StringBuilder,至于为何会创建这个StringBuidler,和 + 这个符号有关系。在Java中,唯一被重载的运算符就是字符串的拼接相关的。+,+=(本来人家是用来做算术运算的)。除此之外,Java设计者不允许重载其他的运算符。@2中str1和str2的类型都是String类型,+连接起来的时候就会将str1和str2先转化为String类型在使用StringBuilder的append方法将两个字符串拼起来,所以35行,出现String.valueOf();

public static String valueOf(Object obj) {
  return (obj == null) ? "null" : obj.toString();
}

下面是StringBuidler的代码:

@Override
public StringBuilder append(String str) {
  super.append(str);
  return this;
}
@Override
public String toString() {
  // Create a copy, don't share the array
  return new String(value, 0, count);
}

可以看到最后会new String(),这样new出来的String是不在常量池中的,所以System.out.println(str5 == str4);//false

以上只是自己的分析,如有错误,欢迎轻拍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容