intern作用
intern用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。
如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。
案例分析
请先看字符串常量池,不然真的理解不透彻
jdk1.8测试:
案例一:
public static void main(String[] args) { //先在常量池放入1,再在堆上生成String obj,obj的char[] value指向常量池的1,栈上s1指向String obj String s1 = new String("1"); //1已经在常量池了,所以这行代码没有任何意义 s1.intern(); //栈s2指向常量池的1 String s2 = "1"; //s1指向String obj, s2指向常量池,肯定不相等 System.out.println(s1 == s2);//flase //用StringBuilder append 1和2,会把1和2放入到常量池中,堆中生成一个StringObj, obj的char[]value=12 //注意此时常量池没有12,value不是指向常量池了,而是把12存在自己的内存中,栈s3指向obj String s3 = new String("1") + new String("2"); //此时常量池没有12,他会把12的引用即String obj的引用放到常量池中(1.7以前是直接放12到常量池) s3.intern(); //常量池有指向12的引用,把这个引用(即obj的地址)给s4 String s4 = "12"; //s3和s4都指向obj,所以相等 System.out.println(s3 == s4);//true }
案例二:
public static void main(String[] args) { String s1 = "hello";//栈s1指向常量池hello String s2 = " world";//栈s2指向常量池 world String s3 = s1+s2;//StringBuilder append hello和world,s3指向堆的obj,obj的char[]value存hello world //此时常量池没有hello world,把s3的引用存入常量池 s3.intern();//这行代码如果移下一行结果就变了 //s4指向常量池s3的地址 String s4 = "hello world"; System.out.println(s4 == s3);//true }
试着自己画一下图吧
案例三:
public static void main(String[] args) { //toString里面new String(char []value) //往常量池添加计算机,软件这两个字符串 //堆中String obj的char[]value保存计算机软件这个字符串,str1指向堆中obj String str1 = new StringBuilder("计算机").append("软件").toString(); //因为此时常量池没有计算机软件,str1.intern()会把str1的引用添加到常量池并返回str1的引用,所以相等 System.out.println(str1.intern()==str1);//输出true //往常量池添加ja,va这两个字符串 //因为常量池已经有java这个字符串了,堆中String obj的char[]value指向常量池的java,str2指向obj String str2 = new StringBuilder("ja").append("va").toString(); //str2.intern()返回java,而str2指向堆obj,地址不相等 System.out.println(str2.intern() == str2);//输出false }
案例四:
public static void main(String[] args) { String str1 = "a";//str1指向常量池a String str2 = "b";//str2指向常量池b String str3 = "ab";//str3指向常量池ab String str4 = str1 + str2;//str4指向堆String obj,obj的char[] value指向常量池ab String str5 = new String("ab");//str5指向堆String obj, obj的char[] value指向常量池ab System.out.println(str5 == str3);//f System.out.println(str5.intern() == str3);//t System.out.println(str5.intern() == str4);//f String a = new String("ab");//a指向堆String obj, obj的char[] value指向常量池ab String b = new String("ab");//b指向堆String obj, obj的char[] value指向常量池ab String c = "ab";//c指向常量池ab String d = "a" + "b";//d指向常量池ab (编译期确定) String e = "b";//e指向常量池b String f = "a" + e;//f指向堆String obj,obj的char[] value指向常量池ab (StringBuilder实现) System.out.println(b.intern() == a);//f System.out.println(b.intern() == c);//t System.out.println(b.intern() == d);//t System.out.println(b.intern() == f);//f System.out.println(b.intern() == a.intern());//t }