1. 下列代码的运行结果是?
public class Test2 {
public static void main(String[] args) {
String s2 = new String("abc");
String s1 = "abc";
System.out.println(s1 == s2);
}
}
运行结果为:false
拆分理解:以下代码分别在内存中做了什么动作?
String s2 = new String("abc");
创建了两个对象:
在堆内存中的字符串常量池中创建了一个 "abc"对象;
在堆内存中创建了一个 "abc"对象。
String s1 = "abc";
0个:
因为这句代码会在堆内存中的字符串常量池中创建一个 "abc"对象,但是由于 String s2 = new String(“abc”); 这一句代码已经在字符串常量池中创建一个 "abc"对象。
因此,双引号 “” 得到的字符串对象,在字符串常量池中存储,而且相同的内容只会在其中存储一份。
所以,变量s1 会指向 字符串常量池中的已存在对象 “abc”。
System.out.println(s1 == s2);
所以,s1存储的是堆内存中的字符串常量池中的 "abc"对象;s2存储的是堆内存中的 "abc"对象。因此地址不同,运行结果为: false。
第二题
public class Test3 {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab";
String s3 = s2 + "c";
System.out.println(s1 == s3);
}
}
运行结果为:false
拆分理解:以下代码分别在内存中做了什么动作?
String s1 = "abc";
创建了一个对象。在堆内存中的字符串常量池中创建了一个"abc"对象。
String s2 = "ab";
创建了一个对象。在堆内存中的字符串常量池中创建了一个"ab"对象。
String s3 = s2 + "c";
创建了两个对象:
在堆内存中的字符串常量池中创建了一个"c"对象。
"ab"对象与"c"对象进行运算后,在堆内存中得到一个新对象:"abc"。
System.out.println(s1 == s3);
所以,s1存储的对象是在堆内存中的字符串常量池中的 “abc”;s3存储的是在堆内存中的 “abc”。因此地址不同,运行结果为: false。
第三题
public class Test4 {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2);
}
}
运行结果为:true
拆分理解:以下代码分别在内存中做了什么动作?
String s1 = "abc";
创建了一个对象。在堆内存中的字符串常量池中创建一个"abc"对象。
String s2 = "a" + "b" + "c";
Java存在编译优化机制,程序在编译时:"a"+"b"+"c"会直接转成"abc"。
创建了0个对象:
这句代码在堆内存中的字符串常量池中创建一个 "abc"对象,但是由于 String s1 = “abc” 已经在字符串常量池中创建了 "abc"对象;
因此,双引号 “” 得到的字符串对象,在字符串常量池中存储,而且相同的内容只会在其中存储一份。
所以,变量s2 会指向 字符串常量池中的已存在对象 “abc”。
System.out.println(s1 == s2);
所以,s1存储的是字符串常量池中的 "abc"对象;s2存储的是字符串常量池中的 "abc"对象。因此地址相同,运行结果为: true。