1. String的创建
l String s1="abc";
对于java中的字符直接量,jvm会使用一个字符串池来存储他们。
l String s2 = new String("abc");
jvm会首先检查string pool中是否存在名为"abc"的对象,如果存在,则在内存的堆中新建一个名为"abc"的对象,s2指向该对象,即s2是该对象的引用。如果不存在,在首先在String pool中创建一个名为"abc"的对象,再在堆中创建一个名为"abc"的对象,s2是该对象的引用。
eg: String s1 = new String("abc") ;
String s2 = "abc" ;
String s3 = new String("abc") ;
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2.intern() == s3.intern()); //false
分析:在s1创建时,创建了2个对象,一个在string pool中,一个在堆中。s1指向堆中的引用,且两个对象都名为"abc"。在s2创建时,一个对象都没有创建,在s2创建时,会首先检查string pool中是否有名为"abc"的对象,已经存在,所以s2指向了string pool中的对象。在s3创建时,在堆中创建了1个名为"abc"的对象。s3指向该对象。
System.out.println(s1 == s1.intern()); //false
System.out.println(s2 == s1.intern()); //true
System.out.println(s2.intern() == s3.intern()); //true
分析: 执行s1.intern()时,会检查string pool中是否存在名为"abc"的对象,如果存在,则该表达式返回的是String pool中的该对象的引用。在上例中s1.intern()返回的应该是s2。在s2.intern() == s3.intern()是true。两边都返回的是s2.
String hello = "hello" ;
String hel = "hel" ;
String lo = "lo" ;
final String llo = "lo" ;
System.out.println(hello == "hel" + "lo"); //true
System.out.println(hello == "hel" + lo); //false
System.out.println(hello == "hel" + llo);//true
分析:"hel" + "lo":该语句只创建了一个字符串对象。jvm在编译的时候就能够确定该值,然后将该字符串放入String pool中。"hel" + lo:该语句会在jvm编译的时候不能确定该值,必须在运行的时候才能调用lo的值。所以会在堆中新创建一个对象,而不是在string pool中。所以第二句是false。第三句的String是final类型的,会进行"宏替换",就是说,当String被定义为final类型后并进行初始化,该string类型就不能再改变,那么这个final类型本质化已经不是变量,而相当于是一个直接量。相当于"hel" + "lo"了,所以第三句为true