关于常量池的分析

关于常量池的分析

第一种情况

public class Dome {
    public static void main(String[] args) {
        String s1 = "ab";
        String s2 = "ab";
        System.out.println(s1 == s2);

    }
}
//ture

对应的内存分析图

第二种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = "a" + "b";
        String s2 = "ab";
        System.out.println(s1 == s2);

    }
}
//ture

内存图分析:

编译器会进行优化,在编译阶段会把“a”,"b",优化成
字符串“ab”,然后再类加载阶段,把ab字符串纳入到
字符串常量池中。

第三种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = new String("a") + new String("b");
        //会在堆中创建一块新的空间,并将该空间的地址执行栈中引用这个字符串的变量
        s1.intern();
        String s2 = "ab";
        System.out.println(s1 == s2);
    }
}//ture

内存图分析:

当调用s1.intern()方法的时候,会做以下判断
查看当前字符串("ab")在常量池中是否存在
①:存在

若栈中有引用,则返回该字符串(“ab”)在常量池中的地址给栈中引用这个字符串的变量。
若栈中没有引用,则什么也不做。

②:不存在

直接将堆中(不是字符串常量池中)该字符串的地址复制到字符串常量池中,这
样字符串常量池就有了该字符串的地址引用,也可以说此时字符串常量池中的字
符串只是一个对 堆中字符串对象的引用,它们两个的地址相同,然后再把这个地
址返回给栈中要引用这个字符串的变量。

第四种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = new String("ab");
        s1.intern();
        String s2 = "ab";
        System.out.println(s1 == s2);
    }
}
//false

内存图分析

当执行第一行代码的时候,首先去常量池中找字符串“ab”。

如果找到了,则不在字符串常量池中创建一个新对象,直接将堆引用指向字符
串“ab”在常量池中的地址。

如果找不到,此时在堆中和常量池中都会创建该字符串的对象,但是他们地址不
同,一个是堆中对象的地址,一个是字符串常量池中的地址。并让堆中的引用指
向字符串常量池中的地址。

调用intern()方法之前,此时常量池中已经有“ab”,并且栈中
没有任何引用。因此,什么也不做。

当执行第三行代码的时候,因为此时常量池中已经有字符串“ab”,所以此步只是把new
String("ab")在常量池中创建“ab”对象的地址赋值栈中引用s2。

第五种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = new String("ab");
        String s3 = s1.intern();
        String s2 = "ab";
        System.out.println(s3 == s2);
    }
}
//ture

内存图分析

当执行第一行代码的时候,首先去常量池中找字符串“ab”。

如果找到了,则不在字符串常量池中创建一个新对象,直接将堆引用指向字符
串“ab”在常量池中的地址。
如果找不到,此时在堆中和常量池中都会创建该字符串的对象,但是他们地址不
同,一个是堆中对象的地址,一个是字符串常量池中的地址。并让堆中的引用指
向字符串常量池中的地址。
调用intern()方法之前,此时常量池中已经有“ab”,但是栈中
有引用s2,因此,将常量池中的地址返回给s2
当执行第三行代码的时候,因为此时常量池中已经有字符串“ab”,所以此步只是把new
String("ab")在常量池中创建“ab”对象的地址赋值栈中引用s3。

第六种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = new String("a") + "b";
        String s3 = s1.intern();
        String s2 = "ab";
        System.out.println(s3 == s1);
    }
}//ture

内存图分析

第七种情况

public class Dome {

    public static void main(String[] args) {
        String s1 = new String("a") + "b";
        String s2 = "ab";
        String s3 = s1.intern();
        System.out.println(s3 == s1);
    }
}//false

内存图分析

posted @ 2022-11-08 20:22  鸽宗  阅读(30)  评论(0编辑  收藏  举报