先说intern方法的作用.
jdk7及以后,如果串池有,不会放入,返回已有的串池中的对象地址,
如果没有,会把对象的引用地址复制一份,放入串池,并把串池中的引用地址返回
看demo.
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);//false
String s3 = new String("a") + new String("a");
s3.intern();
String s4 = "aa";
System.out.println(s3 == s4);//true
在jdk版本是7或者更高的时候,这两个输出的结果上面的是false,下面的是true.这是为啥呢.
这是因为上面在new string的时候,生成了两个对象,一个是在堆空间new出来的对象,还有一个是在字符串常量池里生成的"1"对象.intern()方法在调用的时候,其实没有做任何的事情,因为在new String的时候,已经在字符串常量池生成了"1"对象.后面s2的时候,它直接指向了字符串常量池里面的对象了,所以s和s2的地址是不一样的,所以为false.
示例图:
下面的String s3 = new String("a") + new String("a");
,这里是在堆空间中new了两个String对象,然后用StringBuilder做了append操作进行拼接,拼接完成以后,最后调用了StringBuilder的toString方法.注意,在toString的时候,它只在堆空间进行了new String的操作,并没有在字符串常量池里面生成字符串对象.
在s3调用intern()方法的时候,才将s3在堆空间的地址值,放在字符串常量池中.所以s4的地址值和s3的是一样的.都是指向s3在堆空间中的地址.
图示
再来,
String s3 = new String("a") + new String("a");
String s4 = "aa";
s3.intern();
System.out.println(s3 == s4);//这里输出false,为什么.
上面这个例子,输出了false,这是为什么.
这是因为,s3在生成的时候,并没有在字符串常量池里面生成"aa"对象的地址引用,s4创建的时候,发现字符串常量池没有"aa"对象,它就直接在字符串常量池里创建了"aa"这个对象.后面s3.intern()的时候,其实没有做任何事情(如果返回的话,他其实是返回字符串常量池里s4的对象地址).现在s3和s4一个在堆空间中,一个在字符串常量池中,地址不同,所以是false.
再来
String s3 = new String("a") + new String("b");
String s4 = s3.intern();
System.out.println(s3 == "ab");//true
System.out.println(s4 == "ab");//true
简单说一下,s4,"ab"都是引用s3在堆空间的地址,所以是true