Java字符串两种声明方式在堆内存中不同的体现

字符串池

String不可变是因为在JDK中String类被声明为一个final类,且类内部的value字节数组也是final的,只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以在运行时节约很多heap空间,因为不同的字符串变量都指向池中的同一个字符串

string1 = "100" 和 new String("100")

public class Test {
    public static void main(String[] args) {
        String string1 = "100";
        String string2 = "100";
        // true
        System.out.println(string1 == string2);

        // 'new String("100")' is redundant
        String string3 = new String("100");
        String string4 = new String("100");
        // false
        System.out.println(string3 == string4);
    }
}

当代码执行到String s1 = "100"时,会先看常量池里有没有字符串刚好是“100”这个对象,如果没有,在常量池里创建初始化该对象,并把引用指向它,如下图,绿色部分为常量池,存在于堆内存中:

当执行到String s2 = "100"时,发现常量池已经有了100这个值,于是不再在常量池中创建这个对象,而是把引用直接指向了该对象

这时候打印System.out.println(s1 == s2)时,由于==是判断两个对象是否指向同一个引用,所以这儿打印出来的就应该是true。

继续执行到Strings3 = new String("100")这时候我们加了一个new关键字,这个关键字呢就是告诉JVM,你直接在堆内存里开辟一块新的内存

继续执行String s4 = new String("100")

这时候再打印System.out.println(s3 == s4)那一定便是false了,因为s3和s4不是指向对一个引用(对象)。

我们在写代码过程中,为了避免重复的创建对象,尽量使用String s1 ="123"而不是String s1 = new String("123"),因为JVM对前者给做了优化

posted @ 2021-03-11 01:16  chenzufeng  阅读(229)  评论(0)    收藏  举报