Java String 的 intern()

public class StringInter {
    static String s1,s2,s3,s4,temp;
    private static void method(){
        s1 = new String("aaa");
        s2 = "aaa";
        System.out.println(s1 == s2);    // false
    }

    private static void method1(){
        s1 = new String("bbb").intern();
        s2 = "bbb";
        System.out.println(s1 == s2);    // true
    }

    private static void method2(){
        s1 = "ccc";
        s2 = "ccc";
        System.out.println(s1 == s2);    // true
    }

    private static void method3(){
        s1 = new String("ddd").intern();
        s2 = new String("ddd").intern();
        System.out.println(s1 == s2);    // true
    }
    private static void method3_1(){
        s1 = new String("ddd").intern();
        s2 = new String("ddd");
        System.out.println(s1 == s2); // false
    }


    private static void method4(){
        s1 = "ab" + "cd";
        s2 = "abcd";
        System.out.println(s1 == s2);    // true
    }
    private static void method5(){
        temp = "hh";
        s1 = "a" + temp;
        // s1是String ,相加之后会得出新的String  如果调用s1.intern() 则最终返回true
        System.out.println(s1.getClass());
        s2 = "ahh";
        System.out.println(s1 == s2);    // false
    }
    private static void method6(){
        temp = "hh".intern();
        s1 = "a" + temp;
        s2 = "ahh";
        System.out.println(s1 == s2);    // false
    }
    private static void method8(){
        temp = "hh".intern();
        s1 = ("a" + temp).intern();
        s2 = "ahh";
        System.out.println(s1 == s2);    // true
    }

    private static void method9(){
        s1 = new String("1");    // 同时会生成堆中的对象 以及常量池中1的对象,但是此时s1是指向堆中的对象的
        s1.intern();            // 常量池中的已经存在
        s2 = "1";
        System.out.println(s1 == s2);    // false,因为s1并没有得到新的引用,用的还是堆中的String对象的引用
    }

    private static void method10(){
        String s3 = new String("1") + new String("2");    // 此时生成了四个对象 常量池中的"1" + 2个堆中的"1" + s3指向的堆中的对象(注此时常量池不会生成"11")
        s3.intern();    // jdk1.7之后,常量池不仅仅可以存储对象,还可以存储对象的引用,会直接将s3的地址存储在常量池
        String s4 = "12";    // jdk1.7之后,常量池中的地址其实就是s3的地址
        System.out.println(s3 == s4); // jdk1.7之前false, jdk1.7之后true
    }

    private static void method11(){
        s3 = new String("2") + new String("2");
        s4 = "22";        // 常量池中不存在22,所以会新开辟一个存储22对象的常量池地址
        s3.intern();      // 常量池22的地址和s3的地址不同
        System.out.println(s3 == s4); // false
    }

    private static void method12(){
        String S1,S2,S3,S4;
        S1 = "AB";
        S2 = "AB";
        S3 = new String("AB");
        S4 = new String("AB");
        System.out.println(S1==S2);
        System.out.println(S1==S3);
        System.out.println(S3==S4);
        S3.intern();
        System.out.println(S1==S3);
        S3 = S3.intern();
        System.out.println(S1==S3);
        /**
         *  S1,S2,S3,S4 中存储的都是引用,S1和S2存储的是"AB"的引用(引用“Axx”,做个标记,为了区别),
         * S3和S4存储的是各自对象的引用(引用“Bxx”和引用“Cxx”)。
         *
         *  S3.intern(); 是由返回值的,返回的是:
         *     去字符串常量池中查找,是否存在"AB"字符串,
         *          如果存在则将其引用(引用“Axx”)返回;
         *          如果不存在就创建,在将引用返回;
         *              理解:此时的创建字符串常量池不仅会记录字符串"AB",还会记录S3的引用为以后返回用,
         *                   就是现在没有引用“Axx”,用S3的引用作为引用“Axx”;
         */

    }

    public static void main(String[] args) {
        // method10();
        // method3_1();
        // method12();
        // method5();
        method11();

    }

}

method12的图

 
       直接使用双引号声明出来的String对象会直接存储在字符串常量池中,如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。

 

综上来看最重要的就是以下内容:

对于什么时候会在常量池存储字符串对象,我想我们可以基本得出结论:
    1. 显示调用String的intern方法的时候;
    2. 直接声明字符串字面常量的时候,例如: String a = "aaa";
    3. 字符串直接常量相加的时候,例如: String c = "aa" + "bb"; 其中的aa/bb只要有任何一个不是字符串字面常量形式,都不会在常量池生成"aabb"。且此时jvm做了优化,不会同时生成"aa"和"bb"在字符串常量池中;

 

只有确定了什么时候会在常量池中存储字符串对象,才能接着向下判断。

 

参考链接:

https://www.cnblogs.com/Kidezyq/p/8040338.html

https://blog.csdn.net/ifwinds/article/details/80849184

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值