都知道string常量表最开始是存储编译时就可以确定的string常量。
据说,jdk1.6以后这个常量表放到了堆中。
什么是编译时可以确定 的string常量,而什么不是?看代码
public static void main(String[] args){ String s1 = "abcdefg"; String s2 = randString(7); System.out.println(s1==s2); // false System.out.println(s1.equals(s2)); //true } static char[] cs = new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n'}; static String randString(int len){ String string = ""; for(int i=0;i<len; i++){ string += cs[i]; } return string; }
s2 的构造是在程序运行中才可确定的,编译时无法确定,所以s2是在堆中不再产量表中,s1是在常量表中,所以 s1==s2 是false
String s1=new String("abc"); String s2=s1.intern(); System.out.println(s2==s1); //false System.out.println(s2==s1.intern()); //true System.out.println(s1==s1.intern()); //false
从代码中可见intern方法会将s2的值放到常量表中并返回引用。但对s2自身的引用不受影响。
其实为了比较而用intern 是无意义的,且消耗了cpu。因为string.equal 是把其char[] value 拿出来逐个char 是否相等,所以不论string在什么地方,equal肯定是靠谱的。
而intern的意义其实应该是用在那些运行中产生的string中。如这么用
String str = getDataFromDB(); str = str.intern();
这样用的木底时,让str指向常量表中的string,而堆中的string对象无人引用,丢给gc回收。前提是在这个string值有很多重复产生情况并且长久使用,这样就可以节省内存。