S++

千线一眼

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

JVM-StringTable

StringTable的位置

1.8位置

1.6位置


面试题

有这样一个面试题

public class Main{
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a" + "b";
        String s4 = s1 + s2;
        String s5 = "ab";

        String s6 = s4.intern();
        System.out.println(s3 == s4);
        System.out.println(s3 == s5);
        System.out.println(s3 == s6);

        String x1 = new String("c")+new String("d");
        String x2 = "cd";
        x1.intern();
        System.out.println(x1 == x2); 
    }
}

问打印出的结果是怎样的:


解析

  • 常量池中的字符串仅是符号,第一次用到时才变为对象
  • 利用串池的机制,来避免重复创建字符串对象
  • 字符串变量拼接的原理是 StringBuilder (1.8)
  • 字符串常量拼接的原理是编译期优化
  • 可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
一:常量
        String s1 = "a";
        String s2 = "b";

"a"和"b"是常量池中的信息,会被加载到运行时常量池中,但还不是对象
当常量池中的符号被调用,相关的符号才会变为字符串对象(会先到串池中查找是否已经存在这个对象,没有则创建对象)
串池中没有该对象时,此时会将该信息作为key放入哈希表结构的StingTable串池


二:字符串拼接

变量的拼接

        String s4 = s1 + s2;

首先会创建一个StringBulider对象,然后调用其构造方法init()
把要拼接的变量都append()加载到StringBulider对象中
最后调用toString()方法,变为字符串
这里的toString()方法是将字符串作为新的字符串new String()对象返回

常量的拼接

        String s3 = "a" + "b";

是编译期的优化
会将常量进行直接拼接,而不是一个个单独去常量池中找
所以这里是直接拼接为 "ab"


三:intern

intern方法首先会检查常量池中是否有这个对象
有则返回常量池中的对象,没有则会将对象入池


答案揭晓

public class Main{
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a" + "b"; // 常量字符串拼接,编译期优化为"ab"
        // 两个变量的拼接由StringBuilder拼接为一个新的字符串
        String s4 = s1 + s2; // 新的字符串 new String("ab") 在堆中
        // 前面的创建s3时,使得常量池中已经有"ab"这个字符串
        // s5直接从常量池中获取"ab"这个字符串
        String s5 = "ab";
        // intern方法首先会检查常量池中是否有这个对象
        // 有则返回常量池中的对象,没有则会将对象入池
        String s6 = s4.intern();
        System.out.println(s3 == s4); // false
        System.out.println(s3 == s5); // true
        System.out.println(s3 == s6); // true

        String x1 = new String("c")+new String("d"); // new String("cd"),在堆中
        String x2 = "cd"; // 常量池中的 "cd" 对象
        x1.intern(); // 常量池中已经有 "cd" 这个对象,入池不成功
        System.out.println(x1 == x2); // fasle
        // 如果是调换x1、x2的位置,这里的结果应该为 true
    }
}
false
true
true
false

posted on   S++  阅读(15)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示