首先明确一下常量池这个概念, 它可以用来存储字符串常量
先来看一个程序
public class StringDemo1 {
// A.3 B.4 C.5 D.6
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = new String("abcd");
}
}
请问这个程序开辟了几个空间
答案是c选项
首先看第一行String str1 = new String(“abc”); 在编译阶段JVM先去常量池中开辟一个空间存储abc. 在运行期间, 通过String类的构造器在堆内存中new了一个空间, 然后将String池中的abc复制一份存放在该堆空间中, 在栈中开辟名字为str1的空间, 存放堆中new出来的这个String对象
再来看第二行String str2 = new String(“abc”);
首先在常量池中查找是否存在abc, 存在, 所以只在栈中开辟一个名字为str2的空间
第三行和第一行同理, 所以也是开辟了两个空间
所以一共开辟了5个空间
再来看一个程序
public class StringDemo2 {
public static void main(String[] args) {
String str1 = "abc";//直接赋值
String str2 = "ab";
String str3 = "c";
String str4 = str2 + str3;//传递引用
String str5 = str2 + str3;
String str6 = new String("abc");//通过new赋值
String str7 = "ab"+"c";
String str8 = str2+"c";
System.out.println(str1 == str6);
System.out.println(str1 == str4);
System.out.println(str4 == str5);
System.out.println(str1 == str7);
System.out.println(str1 == str8);
}
}
首先看一下创建字符串的方式 String str1 = “abc”;
在编译器, JVM会去常量池查找是否存在abc, 如果不存在, 就要在常量池中开辟一个新的空间来储存abc在常量池中的地址值.
总结:
String str1 = “abc”;在初始化的时候可能创建了一个对象, 也可能一个对象都没有创建
String str1 = new String(“abc”); 在初始化的时候, 因为new关键字, 所以至少在内存中创建了一个对象, 也有可能是两个对象
再回到这道题
首先明确一下 == 比较的是地址
第一行str1 == str6, 因为new就在堆上开辟了新的内存空间, 所以是false
第二行str1 == str4, 字符串拼接的时候, String会转为StringBuilder, 调用append, 所以也是false
第三行str4 == str5, 同上, false
第四行str1 == str7, 纯常量的拼接不会转化为StringBuilder, 直接在常量池中寻找是否存在已有值. 所以是true
第五行str1 == str8, 同第二行, false
## 总结:
字符串拼接的时候, String -> StringBuilder, 调用append方法
纯常量的拼接不会转为StringBuilder, 直接在常量池内找是否存在已有值