public class StringTest {
public static void main(String[] args) {
String a = new String("123456");
String b = "123456";
String c = "123"+"456";
String d = "123";
String e = "456";
String f = d+e;
System.out.println("a==b:"+(a==b));
System.out.println("b==c:"+(b==c));
System.out.println("b==f:"+(b==f));
System.out.println("c==f:"+(c==f));
System.out.println("a.intern()==b:"+(a.intern()==b));
}
}
普遍答案是:
false
false
false
false
不知intern是什么意思
正确答案是:
false
true
false
false
false
true
什么是String驻留机制?
顾名思义,驻留就是在内存中保留(在Java中,我们通常称驻留对象的地方为驻留池,不过它也是内存的一部分),它不仅存在于Java中,在C#中同样存在。字符串驻留池是JVM初始化时创建一个内部哈希表,表的key是字符串,value是托管堆中String的引用,该表就是驻留池。因为字符串是不变量,如果内存中存在多个相同字符串的实例,便会造成内存的浪费,故高级语言(C#、Java)等都用了字符串驻留池来提高内存利用率。此外,值得注意的一点是,驻留池是不会被GC回收的,它会在程序运行期间一直保留。
那b==c为true,为什么c==f为false呢?
因为“123”与“456”是常量,在编译时期就已经确定了,所以c的值还是驻留池里的“123456”字符串对象,而所有涉及到引用的地方都是在运行时才确定值的,会产生一个新的对象。
当程序执行String a = new String(“123456”)的时候,java做的事包括: 检查123456这个字符串对象是否在驻留池中,如果存在就把它当做值,不存在就放进去,然后再在堆上创建一个String类型的对象放到堆中。所以这段程序有可能生成两个各对象,有可能生成一个对象。前提看驻留池是否存在此字符串。
此外,还要说明一个string.intern()方法,看看a.intern()==b的结果就知道了,a.intern()的作用是去驻留池中查找是否存在与a具有相同unicode的字符串,如果存在则返回驻留池的引用,如果不存在就存放此字符串的值(非引用)进去驻留池,并返回驻留池引用,所以a返回的引用与b是相同的,所以为true。