对Java中String.intern()方法的理解

String.intern()在API中的解释


public class A {

	public static void main(String[] args) {
		String s1 = new StringBuilder("go")
			    .append("od").toString();
		System.out.println(s1.intern() == s1);
		String s2 = new StringBuilder("ja")
			    .append("va").toString();
		System.out.println(s2.intern() == s2);
		String j="java11234";
		String s3 = new StringBuilder("ja")
			    .append("va11234").toString();
		System.out.println(s3.intern() == s3);
		String s4 = new StringBuilder("go")
			    .append("od").toString();
		System.out.println(s4.intern() == s4);
	}

}

在JDK7中运行此程序,结果为:

true
false
false
false

String的intern()方法会得到字符串对象在常量池中和它相等的字符串的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用,所以(s1.intern() == s1)的结果为true。JDK 1.7(以及部分其他虚拟机,例如JRockit)的intern()实现不会再复制实例,只是在常量池中记录首次出现的实例引用,因此intern()返回的引用和由StringBuilder创建的那个字符串实例是同一个。

而如果在JDK1.6中,intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串的实例的引用,而StringBulder创建的字符串实例在Java堆上,所以必然不是同一个引用,(s1.intern() == s1)的结果将返回false。

以上为JDK1.6和1.7中intern()方法的区别

而对于(s2.intern() == s2)比较返回false,因为“java”这个字符串在执StringBuilder.toString()之前已经出现过,所以字符串常量池中已经有它的引用了。不符合首次出现的原则。

为什么常量池中有“java”???原因是因为:java虚拟机会自动调用System类,System类会调用了initializeSystemClass方法,从而在此方法中调用了Version对象的init静态方法sun.misc.Version.init();Version类定义的私有静态字符串常量如下"java"、"1.7.0_51"、"Java(TM) SE Runtime Environment"、"1.7.0_51-b13"。因此sun.misc.Version类会在JDK类库的初始化过程中被加载并初始化,并对其静态常量字段根据指定的常量值做默认初始化,所以"java"被加载到了字符串常量池中,修改上面代码使字符串值为上面常量中的任意一个都会返回false。

同样(s3.intern() == s3)结果也为false,因为在其前面已经出现了和他字符串相等的声明,所以也不符合首次出现的原则

而(s4.intern() == s4)也类似,应为前(s1.intern() == s1)已经将该字符串将被添加到常量池中,所以不符合首次出现原则

而对于

public class A1 {
	public static void main(String[] args) {
		String str1 = new StringBuilder("hello").append("word").toString();
		System.out.println(str1==str1.intern());
		String str2 = new StringBuilder("hellojava").toString();
		System.out.println(str2==str2.intern());
	}
}

运行结果为

true
false

是因为

String str1 = new StringBuilder("hello").append("word").toString();
System.out.println(str1==str1.intern());

等价于下面的代码

String x = "hello";
String y = "word";
String str1 = new StringBuilder(x).append(y).toString();
System.out.println(str1==str1.intern());
“helloword” 最先创建在堆中 ,str1.intern()然后缓存在字符串常连池中 运行结果为true.(符合首次出现原则)

而对于

String str2 = new StringBuilder("hellojava").toString();
System.out.println(str2==str2.intern());

则等价于:

String x = "hellojava";
String str2 = new StringBuilder(x).toString();
System.out.println(str2==str2.intern());

“hellojava” 最先创建在常量池中, 运行结果为false.(违反了首次出现原则)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值