当前位置 : 主页 > 编程语言 > 其它开发 >

JVM_字符串常量池地址问题

来源:互联网 收集:自由互联 发布时间:2022-05-30
先看下代码 public class JVMDemo { public static void main(String[] args) { String s1 = "ab"; //new String() - jdk1.8后永远指向常量池中的引用(没有就在常量池中创建,不会把s2复制到常量池(区别jdk1.6))
先看下代码
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") 会在堆中都创建对象,因此创建了一个对象。该对象与常量池中对象地址不同。

网友评论