关于String的intern()方法,记录一个困惑已久的问题

先看下面一段代码:

    public static void main(String[] args) {
        String str1 = new String("ja") + new String("va");
        String intern1 = str1.intern();//line1
        String s1 = "java";//line2
        System.out.println("str1==intern1:" + (str1 == intern1));//false
        System.out.println("s1==intern1:" + (s1 == intern1));//true
        System.out.println("s1==str1:" + (s1 == str1));//false
        System.out.println("--------------------------");
        String str2 = new String("爪") + new String("哇");
        String intern2 = str2.intern();//line3
        String s2 = "爪哇";//line4
        System.out.println("str2==intern2:" + (str2 == intern2));//true
        System.out.println("s2==intern2:" + (s2 == intern2));//true
        System.out.println("s2==str2:" + (s2 == str2));//true
    }

初看运行结果,我也觉得相当困惑,为什么同样的代码结构返回结果不一样的,后来查阅资料才知道,对于new出来的字符串,调用intern()方法时,intern()方法会把首次遇到的字符串,在常量池中记录首次出现的实例的引用,也就是说,因此intern()返回的引用和new创建的那个字符串的实例是同一个,故而str2==intren2,因为"爪哇"在字符串常量池中原本是不存在的,而"java"在字符串常量池中原本是存在的,所以intern2返回的就是str2的引用,而intern1返回的是原本在字符串常量池中存在的引用。s1直接用双引号赋值,自然就是字符串常量池中的引用,s2同理。

下面调换上述代码中line1和line2的位置,line3和line4位置。

运行结果就变了("爪哇"的结果的变了)。

    public static void main(String[] args) {
        String str1 = new String("ja") + new String("va");
        String s1 = "java";
        String intern1 = str1.intern();
        System.out.println("str1==intern1:" + (str1 == intern1));//false
        System.out.println("s1==intern1:" + (s1 == intern1));//true
        System.out.println("s1==str1:" + (s1 == str1));//false
        System.out.println("--------------------------");
        String str2 = new String("爪") + new String("哇");
        String s2 = "爪哇";
        String intern2 = str2.intern();
        System.out.println("str2==intern2:" + (str2 == intern2));//false
        System.out.println("s2==intern2:" + (s2 == intern2));//true
        System.out.println("s2==str2:" + (s2 == str2));//false
    }

为什么呢,这是因为 String s2 = "爪哇";在String intern2 = str2.intern();之前执行,在调用intern之前调用了 String s2 = "爪哇",而调用 String s2 = "爪哇"之前字符串常量池中是没有 "爪哇",故而在字符串常量池新创建 "爪哇"的引用,并且指向s2,而此时再调用str2的intern方法,字符串常量池中已存在 "爪哇",直接返回了 "爪哇"的引用给intern2,也就是s2和intern2指向的同一个引用。还是回到了最初那句话,调用intern()方法时,intern()方法会把首次遇到的字符串,在常量池中记录首次出现的实例的引用。

 

再看下面一段代码的运行的结果,理解会更加深刻:

        String str3_1 = new String("爪") + new String("哇");
        String str3_2 = new String("爪") + new String("哇");
        System.out.println(str3_1 == str3_2);//false
        String intern1 = str3_1.intern();//line5
        String intern2 = str3_2.intern();//line6
        System.out.println(intern1 == intern2);//true
        System.out.println(intern1 == str3_1);//true

str3_1和str3_2在堆中分别创建两个对象,两个直接比较肯定不同,第一个false很好理解。随后调用str3_1的intern()方法,字符串常量池中不存在"爪哇",将str3_1在堆中的地址引用复制到字符串常量池,而随之调用str3_2的intern()方法,此时字符串常量池中已存在"爪哇",直接将该引用返回给intern2,也就是说str3_1、intern1、intern2指向的是同一块地址。

而将line5、line6调换位置,结果可想而知,此时就是str3_2、intern1、intern2指向的是同一块地址了。

参考文章:https://www.cnblogs.com/wangshen31/p/10404353.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值