“java“.intern==“java“为false(intern方法解析)

对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

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

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。
而对于(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™ 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.(违反了首次出现原则)

猜你喜欢

转载自blog.csdn.net/weixin_43556773/article/details/109759080