不同JDK版本中String.intern()方法的区别

目录

 

基础知识

 

String.intern()解析


基础知识

在Java中创建String对象有两种方法分别为:

String a = "123";
String b = new String("456");

这两种方法有什么本质的区别呢?先来看看String a = "123";是如何生成的,其主要步骤分为两步:

1、判断常量池有没有“123”对象

2、如果有,a直接指向“123”;如果没有,在常量池创建“123”对象,然后使a指向。

由于之前常量池没有“123”对象,所以就创建一个并使a指向它。 

接着,来看看String b = new String("456");是如何创建的,其主要步骤也分为两步:

1、在堆内存中单独开辟出一个内存空间存放“456”对象,使b指向它。

2、如果常量池中没有“456”对象则创建,如果有则不创建。

了解两种不同的创建String类的方法,就可以得到以下两个结论:

1、使用直接赋值,如果对象内容是一样的,则引用地址也是一样的。

2、使用new赋值,即使对象内容是一样的,引用地址也是不一样的。

String a = "123";
String b = "123";
System.out.println(a == b);  //true


String c = new String("123");
String d = new String("123");
System.out.println(c == d);  //false

 

String.intern()解析

JDK1.6及以前,inter()方法是这样描述的:

当字符串在常量池存在时,则返回常量池中的字符串;当字符串在常量池不存在时,则在常量池中拷贝一份,然后再返回常量池中的字符串。

 还是拿之前的两种不同方式为例:

由于两种创建对象的方法都会在常量池中有一份字符串,所以直接返回常量池对象。区别在于,返回的引用地址不同。

String a = "123";
String m = a.intern();
System.out.println(a == m);  //true

String b = new String("456");
String n = b.intern();
System.out.println(b == n);  //false

 之前的例子已经在常量池中存在字符串了,重点在于常量池如果没有字符串的例子,看以下的例子:

String a = new String("1")+new String("2");
String b = a.intern();
System.out.println(a == b);  //false

一步一步来分析,首先第一行String a = new String("1")+new String("2");中应分分为三步来完成:

1、分别在堆内存和常量池创建“1”字符串

2、分别在堆内存和常量池创建“2”字符串

3、运算加法,在堆内存中创建“12”字符串(注意:由StringBuffer实现,并不会在常量池中创建)

此时,走到第二步a.intern();根据JDK1.6时的流程是在常量池中拷贝一份“12”字符串,然后将字符串返回给b。

可以清除的看到a和b的引用地址并不一样,所以返回false。

此时再来看看JDK1.6以后是如何定义intern()方法的:

当字符串在常量池存在时,则返回常量池中的字符串;当字符串在常量池不存在时,则把堆内存中此对象引用添加到常量池中,然后再返回此引用。

 可以看到如果字符串已经在常量池中的话,是和JDK1.6及以前没有任何区别的。所以仍然满足:

String a = "123";
String m = a.intern();
System.out.println(a == m);  //true

String b = new String("456");
String n = b.intern();
System.out.println(b == n);  //false

但当常量池中没有字符串时情况就发生了变化:

String a = new String("1")+new String("2");
String b = a.intern();
System.out.println(a == b);  //true

同样一步一步分析,第一步是一样的: 

当执行到 String b = a.intern();是就发生 了变化:

可以看到,JDK1.6及以前是将堆内存的对象拷贝一份到常量池中,JDK1.6以后是将此对象的引用放入常量池中。 所以JDK1.6以后,实际上b指向的是堆内存中的“12”,即和a指向是相同的,所以返回true。

因此,JDK1.6以后的intern()方法可以有效的减少内存的占用,提高运行时的性能。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值