在java8中,String调用了intern()方法,如果常量池里面有此字符串,那么返回此字符串,如果有引用,则返回这个引用;如果没有就将这个字符串的引用或者字符串(有引用放引用)放入常量池。比如下面代码
String str1=new String("a")+new String("b");
str1.intern();//这句话之后字符串池存着“ab”的引用
String str2="ab";//从字符串常量池找字符串或者指向字符串的引用
System.out.println(str1==str2);//true
这里解释一下:
①执行完new String("a")+new String("b")之后,堆中有a、b、ab对象,(但是请注意字符串常量池却没有ab字符串,类似的还有new String("XX")+"YY"或者str+“ZZ”,(append相加也不会)简单来说相加的形式只要其中有非字面量,那么就不会在常量池创建这个相加的结果字符串)
②之后执行str1.intern()方法,因为字符串常量池没有“ab”的引用或者字符串,那么将这个引用放入字符串常量池,这里就是str1的引用地址
③接着执行str2=“ab”,现在常量池找是否有“ab”的引用或者字符串,在第二步中,“ab”的引用已经放到了字符串常量池,那么这里就会直接返回这个引用,即str1的指向地址,所以str1和str2指向同一个地址,引用相同,返回true
再来说说下面情况
String str7=new String("hello");
str7.intern();
String str8="hello";
System.out.println(str7==str8);//false
在执行new String("hello")的时候,除了在堆中创建hello对象外,字符串常量池也会创建一个hello字符串,所以在str7.intern()的时候,并没有像第一种情况一样把引用放入常量池,因为已经有了,str8=“hello”,将str8指向字符串常量池的“hello”字符串,str7指向堆中的引用,所以str7和str8引用不同,返回false