题目如下:
下面main方法输出是什么?
public static void main(String[] args) {
String str = "abc" + "def";
String str2 = "abcdef";
String str3 = "abc" + new String("def");
String str4 = new String("abc") + new String("def");
String str5 = new String("abcdef");
System.out.println(str==str2);
System.out.println(str==str3);
System.out.println(str2==str3);
System.out.println(str==str4);
System.out.println(str==str5);
System.out.println(str3==str4);
System.out.println(str4==str5);
System.out.println(str2==str5);
}
先放答案:
true
false
false
false
false
false
false
false
惊不惊喜意不意外,接下来解释原因。
话不多说,先javac一下,再javap一下,反解析出汇编码文件:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String abcdef
2: astore_1
3: ldc #2 // String abcdef
5: astore_2
6: new #3 // class java/lang/StringBuilder
9: dup
10: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
13: ldc #5 // String abc
15: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: new #7 // class java/lang/String
21: dup
22: ldc #8 // String def
24: invokespecial #9 // Method java/lang/String."<init>":(Ljava/lang/String;)V
27: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
33: astore_3
34: new #3 // class java/lang/StringBuilder
37: dup
38: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
41: new #7 // class java/lang/String
44: dup
45: ldc #5 // String abc
47: invokespecial #9 // Method java/lang/String."<init>":(Ljava/lang/String;)V
50: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
53: new #7 // class java/lang/String
56: dup
57: ldc #8 // String def
59: invokespecial #9 // Method java/lang/String."<init>":(Ljava/lang/String;)V
62: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
65: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
68: astore 4
70: new #7 // class java/lang/String
73: dup
74: ldc #2 // String abcdef
76: invokespecial #9 // Method java/lang/String."<init>":(Ljava/lang/String;)V
79: astore 5
81: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
84: aload_1
85: aload_2
86: if_acmpne 93
89: iconst_1
90: goto 94
93: iconst_0
94: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
97: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
100: aload_1
101: aload_3
102: if_acmpne 109
105: iconst_1
106: goto 110
109: iconst_0
110: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
113: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
116: aload_2
117: aload_3
118: if_acmpne 125
121: iconst_1
122: goto 126
125: iconst_0
126: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
129: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
132: aload_1
133: aload 4
135: if_acmpne 142
138: iconst_1
139: goto 143
142: iconst_0
143: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
146: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
149: aload_1
150: aload 5
152: if_acmpne 159
155: iconst_1
156: goto 160
159: iconst_0
160: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
163: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
166: aload_3
167: aload 4
169: if_acmpne 176
172: iconst_1
173: goto 177
176: iconst_0
177: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
180: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
183: aload 4
185: aload 5
187: if_acmpne 194
190: iconst_1
191: goto 195
194: iconst_0
195: invokevirtual #12 // Method java/io/PrintStream.println:(Z)V
198: return
接下来依次对每行java代码进行解析:
-
String str = "abc" + "def";
面试最常问的最基本问题,指令如下:即+操作被jvm优化,为常量池中创建abcdef,并赋值给引用
共计一个对象
字符串常量的“+”号连接Java虚拟机会在程序编译期将其优化为连接后的值。 -
String str2 = "abcdef";
同上,即常量池中创建abcdef,并赋值给引用
共计一个对象 -
String str5 = new String("abcdef");
这应该更容易理解,就是先创建了string对象,后在常量池创建abcdef,并使用常量池中的字符串构建string对象。
共计创建了2个对象 -
String str3 = "abc" + new String("def");
1.先创建一个StringBuilder对象
2.常量池中创建abc
3.StringBuilder对象调用append方法拼接abc
4.创建String对象
5.常量池中创建def,并使用常量池中的def构建String对象
6.StringBuilder对象调用append方法拼接
7.StringBuilder对象调用toString方法转成String,toString代码如下,实际上StringBuilder.toString()方法实际上调用的是 public String(char value[], int offset, int count) 构造方法,即使用char数组又创建了一个String对象。
共计创建了5个对象。 -
String str4 = new String("abc") + new String("def");
1.先创建一个StringBuilder对象
2.创建String对象
3.常量池中创建abc,并使用常量池中的abc构建String对象
4.StringBuilder对象调用append方法拼接abc
5.创建String对象
6.常量池中创建def,并使用常量池中的def构建String对象
7.StringBuilder对象调用append方法拼接
8.StringBuilder对象调用toString方法转成String,toString代码逻辑同上,实际上StringBuilder.toString()方法实际上调用的是 public String(char value[], int offset, int count) 构造方法,即使用char数组又创建了一个String对象。
共计创建了6个对象
所以只有直接引用常量池中的字符串的str与str2使用==相同,其他一律不同。