str1 + str2 = str3
没错,这就是简单的字符串拼接,也是在日常开发中运用比较广泛的一种写法。
小编我在上篇文章:Java — String 的内存分配 主要从内存角度,聊了聊 String。
今天呢,借着上篇文章的余热,从字节码 角度,分析一下 字符串拼接 的 底层原理。
【大家也可以关注微信公众号 “皮皮克克” 进行查阅】
一,字符串拼接实例演示
public class StringNewTest {
public static void main(String[] args) {
String s1 = "pipic";
String s2 = "keke";
String s3 = "pipickeke";
String s4 = "pipic" + "keke";
String s5 = s1 + "keke";
String s6 = "pipic" + s2;
String s7 = s1 + s2;
String s8 = s6.intern();
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
System.out.println(s3 == s8);//true
}
}
执行结果:
D:\jdk\jdk1.8.0_171\bin\java.exe
true
false
false
false
false
false
false
true
其实由上面这些执行结果,可以总结字符串拼接:
1,常量与常量的拼接结果在常量池,原理是编译器优化。
2,常量池中不会存在相同内容的常量。
3,只要其中一个是变量,结果就在堆中。变量的拼接原理是StringBuilder。
4,如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象的地址
大家伙可以看看,下面我们来具体分析。
二,字符串拼接底层原理
1,代码:
public class StringNewTest {
@Test
public void test1(){
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2;
System.out.println(s3 == s4);
}
}
结果:
D:\jdk\jdk1.8.0_171\bin\java.exe
false
2,查看字节码指令
我们分析主要的前几行指令:
(1) 从字符串常量池中加载字符串常量,分别是 “a”,“b”,“ab”
(2) 创建 StringBuilder 对象,并初始化
(3) 完成拼接,.append(“a”).append(“b”)
(4) toString(),返回字符串对象地址
注意: 可以发现,这个过程中, 只是在堆空间中, 通过StringBuilder的append()方法,拼接成字符串 “ab”,最后调用 toString(),创建了新的String对象,即 new String(“ab”)。
所以,代码中 s3 = "ab", s4 = s1 + s2,s3 == s4 为 false。
懂了?
结束语:
本文已更新至微信公众号 “皮皮克克”,
欢迎各位小伙伴的查看。