补充:String.intern()方法
intern方法用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后返回引用。
先做基本了解
intern()判断这个常量是否存在于常量池。
(1)如果存在
1.1判断存在内容是引用还是常量,
如果是引用,
返回引用地址指向堆空间对象,
如果是常量,
直接返回常量池常量
(2)如果不存在,
2.1将当前对象引用复制到常量池,并且返回的是当前对象的引用
String a1 = "AA";
System.out.println(a1 == a1.intern()); //true
String a2 = new String("B") + new String("B");//a2 堆中
a2.intern();// 把堆中a2的地址放入常量池
String a3 = new String("B") + new String("B");//a3 堆中
System.out.println(a2 == a3.intern());//true
System.out.println(a3 == a3.intern());//false
String a4 = new String("C") + new String("C");//a4堆中
System.out.println(a4 == a4.intern()); //true
看不明白?下面一句句看图对照
string a1="AA";//图中标注1的过程,在常量池中创建
System.out.println(a1 == a1.intern()); //true
a1调用intern()方法由于,常量池中已经有了一个"AA",所以它返回了它"AA"地址,所以比较的结果时true;
String a2 = new String("B") + new String("B");//a2 堆中
使用了new,则a2是在堆中创建一个"BB"对象,并将"B"存入常量池;
a2.intern();// 把堆中a2的地址放入常量池
由于常量池中没有"BB"这个字符串,所以这个方法会将a2的地址存入常量池
此时常量池中也就存在"BB"这个字符串了;
String a3 = new String("B") + new String("B");
a3与a2一样在堆中创建了一个对象,a2,a3内容一样但地址肯定不一样;
System.out.println(a2 == a3.intern());//true
这时a3调用intern()方法,但由于常量池中可以找到"BB"这个字符串,虽然实际上是存的指向堆空间里"BB"的地址,也就是a2的地址,这样看来a2 == a3.intern()的比较与a2 == a2.intern();是没有区别的;
System.out.println(a3 == a3.intern());//false
a3,intern()是返回的a2的地址,a2,a3是不同的对象,地址肯定不同;
[外链图片转存失败(img-S9QI3Xlh-1565102573494)(C:\Users\Administrator\Desktop\我的坚果云\JAVA\note\image\String.intern()].png)
感觉差不多了就看看下面代码,猜猜结果?
String a4 = new String("ja") + new String("va");// a4堆中System.out.println(a4 == a4.intern());//结果在文档末端
intern()方法总结
1.只在常量池上创建常量
String a1 = "AA";
2.只在堆上创建对象
String a2 = new String("A") + new String("A");
3.在堆上创建对象,在常量池上创建常量
String a3 = new String("AA");
4.在堆上创建对象,在常量池上创建引用
String a4 = new String("A") + new String("A");//只在堆上创建对象AA
a4.intern();//将该对象AA的引用保存到常量池上
5.在堆上创建对象,在常量池上创建引用,不会在常量池中再创建常量。
String a5 = new String("A") + new String("A");//只在堆上创建对象
a5.intern();//在常量池上创建引用
String a6 = "AA";//此时不会再在常量池上创建常量AA,而是将a5的引用返回给a6
System.out.println(a5 == a6); //true
false//原因是常量池一开始就是有一些默认字符串的,而其中Java就是其中一个;
用返回给a6
System.out.println(a5 == a6); //true
**false**//原因是常量池一开始就是有一些默认字符串的,而其中Java就是其中一个;