解析String.intern()


前言

在 JAVA 语言中有8中基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念。常量池就类似一个JAVA系统级别提供的缓存。
String类型的常量池主要使用方法有以下两种(基于JDK7以后的版本)

  • 直接使用双引号声明的String对象会直接存储在常量池中。例如:String str="abc";该语句对在创建常量池中创建一个"abc"字符串对象。

  • 如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。例如:

/*
执行该语句会在字符串常量池中创建对象"abc"和"123",已及JAVA Heap中str引用指向的对象
(还有两个匿名对象new String("abc")、new String("123"),先不做讨论)。
此时str引用的对象内容为"abc123",但此时常量池中没有"abc123"这个对象。
*/
String str=new String("abc")+String("123");
/*执行str.interm();语句是将str中的"abc123"字符串放入 String 常量池中,因为此时常量池中不存在“abc123”字符串*/
str.interm();

通过两段代码进一步理解interm()方法

/*代码段1*/
public static void main(String[] args) {
    String s1 = new String("a");
    s1.intern();
    String s2 = "a";
    System.out.println(s1 == s2);

    String s3 = new String("b") + new String("b");
    s3.intern();
    String s4 = "bb";
    System.out.println(s3 == s4);
}

输出结果为:

false
true

在这里插入图片描述

  • 我们看语句String s1 = new String("a");,生成了常量池中创建"a"和Java Heap中的字符串对象,s1.intern(); 这一句是 s1 对象去常量池中寻找后发现 “a” 已经在常量池里了。
  • 接下来String s2 = "a"; 这句代码是生成一个 s2的引用直接指向常量池中的“a”对象。 结果就是 s 和 s2 的引用地址明显不同。所以输出false
  • s3和s4字符串。String s3 = new String("b") + new String("b");,这句代码中现在生成了2最终个对象,是字符串常量池中的“b” 和 JAVA Heap 中的 s3引用指向的对象。中间还有2个匿名的new String("b")我们不去讨论。此时s3引用对象内容是”bb”,但此时常量池中是没有 “bb”对象的。
  • 接下来s3.intern();这一句代码,是将 s3中的“bb”字符串放入 String 常量池中,因为此时常量池中不存在“bb”字符串,所以在常量池中生成一个 “bb” 的对象,关键点是常量池也在 Java Heap区域,常量池中不需要再存储一份对象了,可以直接存储堆中的引用。这份引用指向 s3 引用的对象。 也就是说引用地址是相同的。因此输出true
/*代码段2*/
public static void main(String[] args) {
    String s1 = new String("a");
    String s2 = "a";
    s1.intern();
    System.out.println(s1 == s2);

    String s3 = new String("b") + new String("b");
    String s4 = "bb";
    s3.intern();
    System.out.println(s3 == s4);
}
false
false

在这里插入图片描述

  • s 1和 s2 代码中,s1.intern();,这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码String s1= new String("a");的时候已经生成“a”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s1 和 s2 的引用地址是不会相等的。
  • 执行String s4 = "bb";声明 s4 的时候常量池中是不存在“bb”对象的,执行完毕后,“bb“对象是 s4 声明产生的新对象。然后再执行s3.intern();时,常量池中“bb”对象已经存在了,因此 s3 和 s4 的引用是不同的。所以俩比较均输出fales

总结

在JDK7后String.intern() 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值