[java基础][字符串]由字符串常量池引发的思考

最近在回头看java基础这块,遇到一段比较有意思的代码

@Test
public void testIntern(){
String s1 = new String("helloworld"); // 堆
String s2 = "helloworld"; //堆中的字符串常量池中
String intern1 = s1.intern(); //internl引用s1的堆对象
System.out.println(s1 == s2); //false
String s3 = new String("helloyeah");       //堆 与 字符串常量池 S3是堆的引用
String intern3 = s3.intern(); //intern3是字符串常量池中引用s3的堆对象
String s4 = "helloyeah"; //字符串常量池里已经有了 helloyeah,所以直接返回这个引用
System.out.println(s3 == s4); //false
System.out.println(intern3 == s4); //true 二者引用的同一个常量
String s5=new String("hello")+new String("yeah"); //堆
System.out.println(s5==s3); //false
String intern5=s5.intern(); // 去常量去查是否有"helloyeah"常量池,发现已经有了s3.intern()的的这个。
System.out.println(intern5==intern3); //true 因为引用相同
System.out.println(intern5==s4); //true 因为引用相同
String s6="helloyeah"; //字符串常量池
System.out.println(s5==s6); //false
String s7=new String("hello")+new String("yeah0"); //堆
String intern7=s7.intern(); //intern7是字符串常量池中引用s7的堆对象
    String s8="helloyeah0";                             //判断常量池中是否有这个字面量是否已经存在引用,发现s7已经有了,则返回intern7
System.out.println(s7==s8);//true
System.out.println(intern7==s8);//true

}

这段代码是来自一篇博文的评论区,本来看完这篇文章,跑了跑代码,感觉没有啥问题,但是看到评论区的时候,发现自己对这块理解的还是有问题。大家可以先想一下上面代码每一次的结果是什么?

https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html这篇文章里说的比较清楚,好好看看

主要就是java7之后,由于字符串常量池从原来的perm space挪到了 heap 区,对intern方法的改变。最大的区别就是java7之后,intern操作后,建立的是一个一个引用,如果字面量字符串存在,则直接引用,如果不存在,则引用的是堆里的对象。

2019-07-13

今天阅读 深入java虚拟机 里提到了这块常量池,文中给出了一个有趣的例子,以及一个简单的判断的方法

 1     @Test
 2     public void testConstantPoolOOM(){
 3         String str2=new StringBuilder("ja").append("va").toString();
 4         System.out.println(str2.intern()==str2);
 5         String str3=new StringBuilder("ja1").append("va").toString();
 6         System.out.println(str3.intern()==str3);
 7         String str4=new StringBuilder("jav").append("a").toString();
 8         System.out.println(str4.intern()==str4);
 9         System.out.println(str2==str4);
10         System.out.println(str4.intern()==str2.intern());
11         String str1=new StringBuilder("计算机").append("234").toString();
12         System.out.println(str1.intern()==str1);
13     }

有趣,是"java"这个字符串为什么会提前在常量池里存在了,简单的判断方法就是判断,常量池里是否首次出现这个字符串,如果是首次,则建立一个引用关系,如果不是首次,则会返回之前引用的引用。

原文地址:https://www.cnblogs.com/lifetraveler/p/11176009.html