intern方法之前总是似懂非懂。今天做了一些测试,总算是明白了一点。
如有错误还请指出
//a程序
String s1 = new StringBuilder("计算").append("机").toString(); //a1
System.out.println(System.identityHashCode(s1)); //a2
String s4 = "计算机";//a3
System.out.println("s1.intern:" + System.identityHashCode(s1.intern())); //a4
System.out.println("s1:" + System.identityHashCode(s1)); //a5
System.out.println("s4:" + System.identityHashCode(s4)); //a6
System.out.println("s4.intern:" + System.identityHashCode(s4.intern())); //a7
/*
输出
1625635731
s1.intern:1580066828
s1:1625635731
s4:1580066828
s4.intern:1580066828
*/
//b程序
String s1 = new StringBuilder("计算").append("机").toString(); //b1
System.out.println(System.identityHashCode(s1)); //b2
System.out.println("s1.intern:" + System.identityHashCode(s1.intern())); //b3
String s4 = "计算机"; //b4
System.out.println("s1:" + System.identityHashCode(s1)); //b5
System.out.println("s4:" + System.identityHashCode(s4));
System.out.println("s4.intern:" + System.identityHashCode(s4.intern()));
/*
输出
1625635731
s1.intern:1625635731
s1:1625635731
s4:1625635731
s4.intern:1625635731
*/
可以尝试着自己先去解释一下。
在a1语句中,共创建了3个对象,“计算”、“机”、new String(char[]…)。要注意这里,在StringBuilder的源码中并没有创建"计算机"这一对象,它只是基于一个char[] 数组上的操作,并且最终在堆上new了一个String对象,但是在常量池中却只有"计算"、“机”。如下图:
所以a2语句输出s1的哈希码,必然是new String(char[])的引用地址。
在执行a3语句的时候,创建了"计算机"这个常量并放入了常量池中。如下图:
在a4中调用s1.intern()后,执行如下步骤:**如果常量池中没有相应的字符串常量,就创建字符串常量,且存放实例的引用,然后返回实例的引用地址,如果常量池中有相应的字符串常量,就返回这个常量的引用。**因为在a3中常量池创建了"计算机"这一常量,所以s1.intern()返回1580066828
那么对于步骤a5:输出s1的实例引用地址,是不会变的1625635731。
对于步骤a6:输出s4的实例引用地址,因为s4直接指向的是常量池中的常量,所以返回1580066828。
对于步骤a7:输出s4.intern(),返回1580066828。
对于b程序,就可以很清楚的明白了。这里不做解释。