第一个问题
String s = new String("Hello");
在内存中创建了几个对象?
答案是2个
- 第一个对象:字面量hello对象,因为字符串常量池中找不到字符串对象,所以就新建了一个字面量"Hello",并把他存入常量池
- 第二个对象:新建了一个String对象 因为有new表示新建一个对象,并引用了字符串对象的内容
- 所以最好用字面量来创建,否则会有new一个对象在堆中开辟一个新的的对象,极大地浪费了内存空间
第二个问题:
String s1 = "123abc";
String s2 = "123abc";
System.out.println(s1==s2);
- 输出是true,因为它们有同一个对象"123abc",所以s2和s1都保存着这个对象的地址
第三个问题
String s1 = "123abc";
String s2 = "123"+"abc";
System.out.println(s1==s2);
- 输出是true,因为编译器在编译时,若发现一个计算表达式可以在编译期间确定结果, 则直接运算好并将结果保存到表达式中 相当于String s2 = “123abc”; s1与s2共用常量池中的对象的地址
第四个问题
String s1 = "123abc";
String s2 = "123";
String s2 = s2+"abc";
System.out.println(s1==s2);
输出是false 因为和上一个问题有区别,上面是编译的时候自动得到字符串,在这种情况下是创建一个新的对象存储"123abc",不会重用常量池的对象,所以两个地址不同,结果是false
第五个问题
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1==s2);
- 输出是false,s1在第一个问题讨论过了,有两个对象,一个是直面量对象,一个是新建的对象保存着内容hello
它们的创建流程:
因为是String数据类型,所以JVM先去常量池 寻找有没有hello字符串,因为没有,所以就创建一个hello字面量对象,引用地址存在常量池中,因为有new,所以新建了一个新的对象,内容是hello,s1因为在main方法里,是局部对象,存地址,指向新建的对象.
s2在常量池中寻找有没有一样的String字符串,发现有,所以不用创建新的字面量对象,s2是局部变量存在栈中,存着引用地址指向字面量对象。
- 引用s1指向的是新建的对象,但是引用s2指向的是直面量对象,所以它们保存的指向对象的地址不符,输出是false。