Loading

JVM_字符串常量池地址问题

先看下代码
public class JVMDemo {
    public static void main(String[] args) {
        String s1 = "ab";
        //new String() -> jdk1.8后永远指向常量池中的引用(没有就在常量池中创建,不会把s2复制到常量池(区别jdk1.6))
        String s2 = new String("ab");
        String s3 = new String("a") + new String("b");
        String s4 = "a";
        String s5 = "b";
        String s6 = s4 + s5;
        String s7 = "a" + "b";
        String s8 =  s4 + "b";

        System.out.println(s1 == s2);//false
        System.out.println(s1 == s3);//false
        System.out.println(s1 == s6);//false
        System.out.println(s1 == s7);//true
        System.out.println(s1 == s8);//false
        System.out.println(s2 == s6);//false
        System.out.println(s2 == s7);//false
        System.out.println(s2 == s8);//false
        System.out.println(s2.intern() == s3.intern());//true
        System.out.println(s2.intern() == s6.intern());//true
        System.out.println(s2.intern() == s8.intern());//true
        System.out.println(s2.intern() == s1);//true
        System.out.println(s2.intern() == s7);//true
    }

}

1、s1为字符串常量,取自常量池中,所有取自常量池中相等的值最终地址都相等。(在jdk1.7之后常量池放在了堆中)

所有字面量字符串均存放在常量池中,一旦有变量的加入,则会在堆中创建对象。

2、String s8 = s4 + "b"中的+到底做了什么

new StringBuilder(s4).append("b").toString()

3、String.intern()的作用是什么

String.intern() --> 返回一个字符串,内容与此字符串相同,若常量池里有相同字符串则返回池中字符串的引用,若没有则将其复制一份添加进池中再返回池中字符串的引用。
public class JVMDemo {
    public static void main(String[] args) {

        String s3 = new String("a") + new String("b");
        s3.intern();
        String s1 = "ab";

        String s2 = new String("cd");
        s2.intern();
        String s4 = "cd";
        
        System.out.println(s1 == s3);//true
        System.out.println(s2 == s4);//false

    }

}
jdk1.6中:字符串常量池是在方法区中,方法区的实现方式是和堆一样的(方便垃圾回收),存放的位置在堆空间的永久代中
永久代中的对象和堆中其他空间的对象肯定是不等的。
jdk1.8中:字符串常量池移到了堆中,方法区中其他内容,比如class信息、运行时常量池还是在方法区中,方法区的存放位置还是在堆空间的永久代中.字符串常量池已经移到了堆中,那么使用intern()方法时,如果常量池没有,就会直接返回堆中对象,因为都在一个地方嘛,所以不需要再重新创建,这和jdk1.8是不一样的,要特别注意!

4、String s2 = new String("ab");做了什么

常量池中无"ab" : new String("ab") 会在堆和常量池中都创建对象,因此创建了两个对象。两个对象地址不同。
常量池中有"ab" : new String("ab") 会在堆中都创建对象,因此创建了一个对象。该对象与常量池中对象地址不同。

posted @ 2022-05-17 17:57  yisk  阅读(73)  评论(0)    收藏  举报