1. String是一个final类,代表不可变的字符序列。
    2. 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的。
    • 例子:

      String s1 = “hello”; s1 = “haha”; 这里一共创建了两个对象。

    String a = “hello” + “abc”; 实际上这里编译器会优化成为:String a = “helloabc”; 所以这里只创建了一个对象。

    分析:

    1. 编译器不傻,做一个优化,判断创建的常量池对象,是否有引用指向
    2. String a = “hello”+”abc”; => String a = “helloabc”;

      String a = “hello”;//创建对象a String b = “abc”;//创建对象b String c = a + b; 一共创建了3个对象,a,b指向的是常量池,c指向的是堆。

    内存布局图:
    字符串特性1 - 图1

    1. package test;
    2. public class Main {
    3. public static void main(String[] args) {
    4. String a = "hello"; //创建 a对象
    5. String b = "abc";//创建 b对象
    6. //1. 先 创建一个 StringBuilder sb = StringBuilder()
    7. //2. 执行 sb.append("hello");
    8. //3. sb.append("abc");
    9. //4. String c= sb.toString()
    10. //最后其实是 c 指向堆中的对象(String) value[] -> 池中 "helloabc"
    11. String c = a + b;
    12. String d = "helloabc";
    13. System.out.println(c == d);//真还是假? 是false
    14. String e = "hello" + "abc";//直接看池, e指向常量池
    15. System.out.println(d == e);//真还是假? 是true
    16. }
    17. }

    image.png

    小结:

    • 底层是StringBuilder sb = new StringBuilder(); sb.append(a);sb.append(b); sb是在堆中,并且append是在原来字符串的基础上追加的。
    • 重要规则, String c1 = “ab” + “cd”;常量相加,看的是池。 String c1 =a+b;变量相加,是在堆中。