一、创建了几个对象
String s = new String(“Hello world”)可能创建两个对象也可能创建一个对象。如果方法区中有“Hello world”字符串常量的话,则仅仅在堆中创建一个对象。如果方法区中没有“Hello world”对象,则堆上和方法区中都需要创建对象。
二、使用+号拼接字符串
public void test1(){
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = "a"+"b";
String s5 = s1 + s2;
System.out.println(s4 == s3);//true
System.out.println(s5 == s3);//false
System.out.println(s5.intern() == s3);//true
}
通过字面量赋值创建字符串时,会先在常量池中查找是否存在相同的字符串,若存在,则将栈中的引用直接指向该字符串;若不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串。
引用变量的拼接:s1+s2
实际上是使用StringBuilder.append来完成,经过编译后的第6行可以发现该行代码被最终会被编译成如下的代码:
String s5 = (new StringBuilder()).append(s1).append(s2).toString();
而toString()
方法里又会new一个String对象返回,所以就和常量直接拼接不相等。
当要在循环中拼接字符串时,应当在循环外创建StringBuilder的对象,避免在循环体中循环的创建StringBuilder对象来实现字符串的拼接。
三、intern()
intern()
方法会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,如果不存在,在常量池中创建这个常量返回引用。
@Test
public void test2(){
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s5 = s1 + s2;
String s6 = new String("ab");
System.out.println(s6 == s3);// false
System.out.println(s6 == s5);// false
System.out.println(s6.intern() == s3);// true
}
@Test
public void test3(){
String s1 = "ab";
String s2 = new String("a");
String s3 = new String("b");
String s4 = s2 + s3;
System.out.println(s4 == s1);//false
System.out.println(s4.intern() == s1);//true
}