java字符串常量池和String:intern()方法

在虚拟机规范中,运行时常量池(包含字符串常量池)是方法区的一部分。在HotSpot虚拟机中,JDK1.6以及之前,使用永久代来实现方法区,所以字符串常量池是在永久代中,在JDK1.7及其以后,字符串常量池被放在堆中实现,String:intern()方法是一个本地方法。当执行字符串的intern()方法后,对不同的字符串赋值方式会有不同的效果,主要有以下两种方式:

 第一种:

String  s1= new String(“我是new出来的对象”);

  Stirng  s2=s1.intern();

第二种:

  String s3 = “我是常量字符串”;

  String s4 = s3.intern();

在分析这两种情况之前,我们从虚拟机规范层面分析一下new String()行为,当执行以下语句时,我们看看发生了什么?

String s1Test =new String(“我是ne出来的对象时”);---------------------1

String s2Test = “我是字符串字面量”;                             ---------------------2

执行1虚拟机会在堆上创建一个对象,然后将栈中的s1变量(该对象的引用)指向该对象。当直接用双引号赋值时(执行2),将栈中的s2Test变量指向常量池中该字符串的引用如下图所示

 

下面我们来分析一下上述两种情况在JDK1.6和1.7及其之后的区别

先看第一种情况在JDK1.6中的实际处理方式:

String  s1= new String(“我是new出来的对象”);

  Stirng  s2=s1.intern();

当执行String  s1= new String(“我是new出来的对象”);会在堆中建立一个对象,同时在字符串常量池中生成一个对象,然后将s1指向堆中new出来的对象的实例。

当执行String s2 = s.intern();

1.如果发现字符串常量池中有该对象,在常量池中生成一个该字符串实例对象的引用,然后返回常量池中该实例对象的引用。

2.如果字符串常量池中有该对象的引用,直接返回常量池中对象的引用

再看第二种情况在JDK1.6中的实际处理方式:

String s3 = “我是常量字符串”;

String s4 = s3.intern();

执行String s3 = “我是常量字符串”;首先检查字符串常量池中有没有该字符串的引用,如果有直接返回,如果没有,在常量池中生成一个该字符串对象,返回指向该对象的引用。并将s3指向常量池中的该字符串的引用。

执行String s4 = s3.intern();由于字符串中已经有了一个字符串引用,所以直接返回。如下图所示:

看完JDK1.6中的处理方式,我们再来看上述两种情况在JDK1.7及其之后的处理方式

在JDK1.7中第一种情况:

String  s1= new String(“我是new出来的对象”);

  Stirng  s2=s1.intern();

当执行String  s1= new String(“我是new出来的对象”);会在堆中建立一个对象,然后将s1指向堆中new出来的对象的实例。

当执行String s2 = s.intern();

1.如果发现字符串常量池中没有该对象的引用,堆中有该对象的实例,然后在常量池中生成个该对象的引用,将该对象的引用指向堆中的实例,与堆中的对象共用一个实例,原因是在JDK1.7及其以后,将字符串常量池放到了堆中去实现,既然堆中有了一个对象,没必要在建立一个。

2.如果字符串常量池中有该对象的引用,直接返回常量池中对象的引用。

 

再看第二种情况在JDK1.7中的实际处理方式:

String s3 = “我是常量字符串”;

String s4 = s3.intern();

执行String s3 = “我是常量字符串”;首先检查字符串常量池中有没有相同的字符串对象的引用,如果有直接返回,如果没有,在常量池中生成一个该字符串对象。返回该对象的引用。

执行String s4 = s3.intern();由于字符串中已经有了一个字符串引用,所以直接返回。如下图所示:

 所以通过上述分析,HotSpot虚拟机在jdk1.7及其以后中,在new String()对象时,对象生成策略发生了改变,不需要在常量池中缓存一个对象实例的副本,而是直接在堆中建立一个对象,调用intern()方法时,只需在常量池中建立一个指向该实例的引用即可。所以调用intern()方法,无论是堆中还是常量池中,实例对象只有一个。这是因为HotSpot虚拟机在jdk1.7及其之后,将字符串常量池放在了堆中去实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值