自学内容网 自学内容网

JAVA软开-面试经典题(7)-字符串常量池

字符串常量池

1.定义:字符串常量池(String Constant Pool),用于存放字符串常量的运行时内存结构,其底层的实现为Hashtable。
【注意】

  • 在JDK1.6之前,字符串常量池中只会存放具体的String实例,在使用String.intern方法时,若字符串常量池中有满足String.equals方法的String对象,则返回其引用;字符串常量池中没有相同的String对象,则当前String对象为堆上对象,故在字符串常量池中创建一个相同的String对象,并返回其引用。

  • 在JDK1.7之后,字符串常量池不仅可以存放String实例,同时还能存放String实例的引用。在使用String.intern方法时,若字符串常量池中有满足String.equals方法的String对象,则返回其引用,这一点和JDK1.6相同;若字符串常量池中没有相同的String对象,则当前String对象为堆上对象,故在字符串常量池中存放一个指向堆上此String对象的引用,并返回此引用。

代码例子1:

public class Test {
    public static void main(String[] args) {
        String s1 = new String("He") + new String("llo");// 堆上创建"Hello","He","llo"实例,String Pool中创建"He"和"llo"实例
        s1.intern();// 将堆上"Hello"的引用存入String Pool
        String s2 = "Hello";// 获取String Pool中的"Hello"的引用
        System.out.println(s1 == s2);// true
    }
}

代码例子2:

public class Test {
    public static String s = "Hello";
    
    public static void main(String[] args) {
        String s1 = new String("He") + new String("llo");
        // 堆上创建"Hello","He","llo"实例,String Pool中创建"He"和"llo"实例
        s1.intern();
        // String Pool中已有"Hello",故没有将s1的引用添加到String Pool中,返回的是String Pool中已有的"Hello"的引用
        String s2 = "Hello";
        // 获取String Pool中的"Hello"的引用
        System.out.println(s1 == s2);// false
        System.out.println(s == s2);// true
    }
}

字符串常量池在JVM的分布

参考《深入理解Java虚拟机》

在这里插入图片描述

intern方法

参考地址见文末

在这里插入图片描述

例子

//字符串常量池:"计算机"和"技术"     
//堆内存:str1引用的对象"计算机技术"  
//堆内存中还有个StringBuilder的对象,但是会被gc回收
//StringBuilder的toString方法会new String(),这个String才是真正返回的对象引用
String str2 = new StringBuilder("计算机").append("技术").toString();   //字面量没有出现"计算机技术"字面量,所以不会在常量池里生成"计算机技术"对象
//"计算机技术" 在池中没有,但是在堆中存在,则intern时,会直接返回该堆中的引用
System.out.println(str2 == str2.intern());  //true


//字符串常量池:"ja"和"va"    
//堆内存:str1引用的对象"java"  
//堆内存中还有个StringBuilder的对象,但是会被gc回收
//StringBuilder的toString方法会new String(),这个String才是真正返回的对象引用
String str1 = new StringBuilder("ja").append("va").toString();    //没有出现"java"字面量,所以不会在常量池里生成"java"对象
//java是关键字,在JVM初始化的相关类里肯定早就放进字符串常量池了
System.out.println(str1 == str1.intern());  //false



//"test"作为字面量,放入了池中
//而new时s1指向的是heap中新生成的string对象
//s1.intern()指向的是"test"字面量之前在池中生成的字符串对象
String s1=new String("test");  
System.out.println(s1==s1.intern());   //false


String s2=new StringBuilder("abc").toString();
System.out.println(s2==s2.intern());  //false
//同上

参考链接:
https://blog.51cto.com/u_15281317/3008750
https://code84.com/21914.html


原文地址:https://blog.csdn.net/qq_42018605/article/details/142930759

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!