都知道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值有很多重复产生情况并且长久使用,这样就可以节省内存。