String str1 = new StringBuilder("计算机").append("软件").toString(); System.out.println(str1.intern() == str1); String str2 = new StringBuilder("ja").append("va").toString(); System.out.println(str2.intern() == str2);
在不同的jdk上面运行产生不同的结果。
在openjdk 1.8上面运行结果是true/true。
这里不纠结不同jdk运行的结果不同,只谈谈String.intern()方法的机制。
new StringBuilder("计算机").append("软件")这段代码在执行的时候就会产生2个字符串"计算机"和"软件"并放入string pool中,因此"计算机软件".intern()的时候由于string pool中没有"计算机软件"这个字符串,根据intern()的定义:如果string pool中存在(equals)这个字符串,则返回string pool中的字符串引用,如果不存在,把这个字符串(复制一份)放入string pool并返回这个字符串引用。因此str1.intern() == str1结果就是true。
str2.intern()时候由于string pool中已经存在"java"这个字符串(作者周志明的解释),因此他说返回结果是false,但是在我的机器上返回结果却是true,可能openjdk 1.8里"java"这个字符串并不存在于string pool中 这里不纠结这个。
String str1 = "str1";//字符串常量直接复制一份到string pool System.out.println(str1.intern() == str1);//true String str2 = "str" + "2";//编译时会优化成"str2" System.out.println(str2.intern() == str2);//true String str3 = new String("str3");//这个时候"str3"是字符串常量,已经进入string pool System.out.println(str3.intern() == str3);//false String str3_2 = new String("str") + new String("3"); System.out.println(str3_2.intern() == str3_2);//false;上面2个字符串str和3是常量,已经放入到string pool,并且"str3"也已经在string pool了(参见前面str3变量) String str4 = new String("str") + new String("4"); System.out.println(str4.intern() == str4);//true;这个就不解释了 String str5 = new StringBuilder("str5").toString();//"str5"是字符串常量,已经存入了string pool System.out.println(str5.intern() == str5);//false; String str6 = new StringBuilder("str").append("6").toString(); System.out.println(str6.intern() == str6);//true;和str4变量一样
上面这些代码运行在openjdk1.8上。
也可以通过javap反编译查看,目前还不会看jvm 指令,以后再研究。