String.intern()方法解析

简介

String.intern()方法是一种手动将字符串加入常量池中的native方法,在此我将其方法分为jdk6和jdk8版本,原理如下:

jdk6:调用该方法时,如果常量池中有该字符串,则返回该字符串(可以理解为String的value指向常量池该常量),如果常量池中没有,则会去堆中查找等价的String对象,并且将它复制到常量池中。

jdk8:调用该方法时,如果常量池中有该字符串,则返回该字符串(可以理解为String的value指向常量池该常量),如果常量池中没有,则会去堆中查找等价的String对象,并且将该对象的引用复制到常量池中。

 实例

代码

话不多说,上代码!!!

@Test
public void test(){

    String s = new String("2");
    s.intern();
    String s2 = "2";
    System.out.println(s == s2);

    String s = new String("3") + new String("3");
    s.intern();
    String s2 = "33"
    System.out.println(s == s2);
}

运行结果

// 请忽略jdk6、jdk8以及空行 为了美观
jdk6:

false
false
-------------------------------------------------------
jdk8:

false
true

解析:

jdk6:

首先new String会生成两个对象 一个存放在常量池,一个存放在堆。我们知道,new对象,引用是指向堆中的。接着我们调用了s.intern(),因为常量池已经存在"2"这一字符,所以会返回常量池中该字符的地址。但是这里我们没有设置一个变量去接收,所以s还是指向堆区。然后我们用一个变量s2等于"2",因为"2"已经在常量池中存在,所以直接返回常量池中"2"的地址。即s指向堆,s2指向常量池。所以为false。

我们来看第二段代码:这里用s = new String("3") + new String("3");实质是StringBuilder来调用append方法。这段代码会在堆区生成"33"这一字符对象,还会在常量池中生成"3"这一字符串常量。然后我们调用了s.intern()方法,由于现在常量池中没有"33"这一常量,所以会从堆中复制过来,同样的,这里我们没有用一个变量去接收,所以s还是指向堆区(如果我们用s去接收,那么s会指向常量池中的"33")。接着我们用s2 = "33",这里就是使s2指向常量池中的"33",所以也为false。

jdk8:

同样我们也来分析这两段代码。首先第一行代码会在堆区生成对象,也会在常量池中生成常量。

我们调用s.intern(),因为常量池中已经存在,所以并没有什么改变。s还是指向堆区。接着你们也知道了,s2指向常量池,固为false。

第二段代码:第一行代码跟上面一样,会在堆区生成"33"字符串对象,常量池生成"3"字符常量,且s指向堆区。当调用s.intern(),由于常量池中没有"33"字符串常量,所以会去堆区查找,查找到了,复制该对象的引用到常量池,你没有看错,就是引用!!!也就是说常量池的"33"存储的是指向堆区"33"的引用。然后s2 = "33",即s2指向常量池"33"字符串常量,而常量池的字符串常量又存储的是指向堆区"33"字符串对象,所以可以理解为s2指向堆区!!!所以就为true!

结束

首先这篇文章是我自己复习八股文时疑惑的地方,权当记录一下。这也是我在查看了许多大佬博客之后自己理解总结的,希望对大家有帮助,如果哪里有错误,请告诉我,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值