- String是一个final类,代表不可变的字符序列。
- 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的。
- 例子:
String s1 = “hello”; s1 = “haha”; 这里一共创建了两个对象。
String a = “hello” + “abc”; 实际上这里编译器会优化成为:String a = “helloabc”; 所以这里只创建了一个对象。
分析:
- 编译器不傻,做一个优化,判断创建的常量池对象,是否有引用指向
- String a = “hello”+”abc”; => String a = “helloabc”;
String a = “hello”;//创建对象a String b = “abc”;//创建对象b String c = a + b; 一共创建了3个对象,a,b指向的是常量池,c指向的是堆。
内存布局图:
package test;
public class Main {
public static void main(String[] args) {
String a = "hello"; //创建 a对象
String b = "abc";//创建 b对象
//1. 先 创建一个 StringBuilder sb = StringBuilder()
//2. 执行 sb.append("hello");
//3. sb.append("abc");
//4. String c= sb.toString()
//最后其实是 c 指向堆中的对象(String) value[] -> 池中 "helloabc"
String c = a + b;
String d = "helloabc";
System.out.println(c == d);//真还是假? 是false
String e = "hello" + "abc";//直接看池, e指向常量池
System.out.println(d == e);//真还是假? 是true
}
}
小结:
- 底层是StringBuilder sb = new StringBuilder(); sb.append(a);sb.append(b); sb是在堆中,并且append是在原来字符串的基础上追加的。
- 重要规则, String c1 = “ab” + “cd”;常量相加,看的是池。 String c1 =a+b;变量相加,是在堆中。