在jdk6及其之前,intern()会将首次遇到的字符拷贝到永久代的字符串常量池中去存储。
jdk7开始去永久化,到jdk8时基本上永久代已经成为了历史,原本存放在永久代中的字符串常量被移至java堆(元空间)之中去
String::intern原理分析:
判断这个常量是否存在于常量池
如果存在
判断存在内容时引用还是常量
如果是引用,
返回引用地址指向的堆空间对象
如果是常量
直接返回常量池常量
如果不存在
将当前对象引用拷贝到常量值,并且返回的是当前对象的引用
说明:测试所使用的jdk8,可能会因为更高版本特性,测试结果可能也会有所不同
总结:
随笔分类
1.只在常量池上创建
String a1 = "a";
2.在堆上创建对象,在常量池上创建常量
String a2 = new String("aa");
3.在堆上创建了对象aaa,bbb,aaabbb,并设置aaa,bbb到常量池
String a3 = new String("aaa") + new String("bbb");
4.在堆上创建对象,在常量池上创建引用
String a4 = new String("aaa") + new String("aaa");
a4.intern();
5.在堆上创建对象,在常量池上创建引用,然后被引用
String a5 = new String("A") + new String("A");
a5.intern();
String a6 = "AA"; //此时不会再在常量池上创建常量,而是将a5的引用返回
System.out.println(a5 == a6); //true
测试:
String b1 = new String("b");
System.out.println(b1.intern() == b1); //显然是false
String b2 = new String("B") + new String("B");
b2.intern();
String b3 = new String("B") + new String("B");
System.out.println(b2 == b3.intern()); //true
System.out.println(b3 == b3.intern()); //false