一 字符串拼接操作
-
常量与常量的拼接结果在常量池,原理是编译期优化
-
常量池中不会存在相同内容的常量
-
只要其中有一个是变量,结果就在堆中,变量拼接的原理是 StringBuilder。
-
如果拼接的结果调用 intern() 方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址
二 实战
1 代码
@Test
public void test1() {
String s1 = "a" + "b" + "c"; // 编译期优化:等同于"abc"
String s2 = "abc"; // "abc"一定是放在字符串常量池中,将此地址赋给s2
/*
* 最终 .java 编译成 .class ,再执行.class 的反编译
* String s1 = "abc";
* String s2 = "abc"
*/
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
System.out.println("----------------");
}
@Test
public void test2() {
String s1 = "javaEE"; // 存储在堆中的字符串常量池
String s2 = "hadoop"; // 存储在堆中的字符串常量池
String s3 = "javaEEhadoop"; // 存储在堆中的字符串常量池
String s4 = "javaEE" + "hadoop"; // 编译期优化,存储在堆中的字符串常量池
// 如果拼接符号的前后出现了变量,则相当于在堆空间中 new String(),具体的内容为拼接的结果:javaEEhadoop
String s5 = s1 + "hadoop"; // 变量 + 常量 ,存储在堆中的非字符串常量池
String s6 = "javaEE" + s2; // 常量 + 变量 ,存储在堆中的非字符串常量池
String s7 = s1 + s2; // 变量 + 变量 ,存储在堆中的非字符串常量池
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
// intern():判断字符串常量池中是否存在 javaEEhadoop 值,如果存在,则返回常量池中 javaEEhadoop 的地址;
// 如果字符串常量池中不存在 javaEEhadoop,则在常量池中存储一份 javaEEhadoop,并返回此对象的地址。
String s8 = s6.intern(); // 存储在堆中的字符串常量池, 其实就是 s3
System.out.println(s3 == s8); // true
}
2 图解
3 测试
true
true
----------------
true
false
false
false
false
false
false
true
4 说明
如果拼接符号的前后出现了变量,则相当于在堆空间中new String(),具体的内容为拼接的结果。
调用 intern 方法,则会判断字符串常量池中是否存在 JavaEEhadoop 值,如果存在则返回常量池中的值,否者就在常量池中创建。
字符串对象在堆中会存储在两个地方:堆中的字符串常量池、堆中的非字符串常量池。
存储在堆中的字符串常量池:s1、s2、s3、s4、s8
存储在堆中的非字符串常量池:s5、s6、s7