String字符串存放位置(常量池)

为什么要用到常量池:

在Java中只要是new的信息都会在堆上开辟一个新的空间,为了解决这个问题,JVM中才出现了字符串常量池的概念。但是只有直接用 ""修饰的字符,才会被加入到常量池中,当再次用 ""创建的时候,会首先从常量池中去获取。
字符串常量池存在于运行时常量池中。也就存在于方法区中。
在这里插入图片描述

public class DemoStringCreation {
    public static void main(String args[]) {
        String str1 = "Hello";
        String str2 = "Hello";
        System.out.println("str1 and str2 are created by using string literal.");
        System.out.println("    str1 == str2 is " + (str1 == str2));
        System.out.println("    str1.equals(str2) is " + str1.equals(str2));  
        String str3 = new String("Hello");
        String str4 = new String("Hello");
        System.out.println("str3 and str4 are created by using new operator.");
        System.out.println("    str3 == str4 is " + (str3 == str4));
        System.out.println("    str3.equals(str4) is " + str3.equals(str4));  
        String str5 = "Hel" + "lo";
        String str6 = "He" + "llo";
        System.out.println("str5 and str6 are created by using string constant expression.");
        System.out.println("    str5 == str6 is " + (str5 == str6));
        System.out.println("    str5.equals(str6) is " + str5.equals(str6));  
        String s = "lo";
        String str7 = "Hel" + s;
        String str8 = "He" + "llo";
        System.out.println("str7 is computed at runtime.");
        System.out.println("str8 is created by using string constant expression.");
        System.out.println("    str7 == str8 is " + (str7 == str8));
        System.out.println("    str7.equals(str8) is " + str7.equals(str8));  
    }
}

运行结果如下:

str1 and str2 are created by using string literal.
    str1 == str2 is true
    str1.equals(str2) is true
str3 and str4 are created by using new operator.
    str3 == str4 is false
    str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
    str5 == str6 is true
    str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
    str7 == str8 is false
    str7.equals(str8) is true

使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。

String s = new String("abc"); //创建了几个对象

两个;
第一个对象是"abc"字符串存储在常量池中;
第二个对象是创建在Heap中的String对象;这里的s是放在栈里面的指向了Heap堆中的String对象。

String s1 = new String("s1") ;
String s2 = new String("s1") ; //创建了几个对象

三个;
第一个是编译期就已经创建在常量池中创建的"s1",因为创建一个之后常量池中就会有,不再创建,直接指向;
后面两个是运行期使用new创建在堆上的s1和s2;

String.intern()的使用

new 出来的 String 类型是否也能使用常量池呢? 当然可以,就是通过 intern 方法。这个方法的意思就是先到缓存中(也就是常量池中)查询当前对象是否存在,存在就返回常量池中地址,不存在就加入常量池。

//双引号直接放入常量池
String s1 ="1";
String s2 =newString("1");
//false
System.out.println(s1 == s2);
//先到常量池中查询是否有”1“,存在就将常量池中对象返回,不存在就放到常量池中(此时常量池中存在s1)
//于是就将s1的值重新复制给s3,所以s1 == s3
String s3 =newString("1").intern();
//true
System.out.println(s1 == s3);
String t1 = new String("2");
解析:创建了两个对象,t1指向堆区

String t2 = "2";
解析:t2指向字符串常量池

t1.intern();
解析:字符串常量池已经存在该字符串,直接返回;

System.out.println(t1 == t2); //false or true
解析:很明显 false

String t3 = new String("2") + new String("2");
解析:过程同问题1 t3指向堆区

String t4 = "22";
解析:t4 在1.61.7中指向不同
t3.intern();
解析: 字符串常量池中已经存在该字符串 直接返回

System.out.println(t3 == t4); //false or true
解析: 很明显为 false 指向不同的内存区

版权声明:本文为weixin_43956958原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。