1.看看下面这段代码执行结果是什么?
String a = "ab";
String b = "a" + "b";
System.out.println((a == b)); //它的执行结果为true;
2.下面这段代码的执行结果是什么?
String a = "ab";
String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //执行结果为false
以上两个执行结果的原因分析:
String b = "a" + "b";编译器将这个"a" + "b"作为常量表达式,在编译时进行优化,直接取结果"ab",这样这个问题退化
String a = "ab";
String b = "ab";
System.out.println((a == b));
然后根据3的解释,得到结果true
javap工具执行查看字节码如下:
0: ldc #16; //String ab
2: astore_1
3: ldc #16; //String ab
5: astore_2
6: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_1
10: aload_2
11: if_acmpne 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokevirtual #24; //Method java/io/PrintStream.println:(Z)V
22: return
通过 0: ldc #16; //String ab和 3: ldc #16; //String ab ,知道该java文件通过编译器编译后都变为 String b = "ab"; 和作者分析的一样。
===========================
对于第二个程序这个好理解,"a" + bb中的bb是变量,不能进行优化。javap查看字节码如下:
0: ldc #16; //String ab
2: astore_1
3: ldc #18; //String b
5: astore_2
6: new #20; //class java/lang/StringBuilder
9: dup
10: ldc #22; //String a
12: invokespecial #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
15: aload_2
16: invokevirtual #27; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #31; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_3
23: getstatic #35; //Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_1
27: aload_3
28: if_acmpne 35
31: iconst_1
32: goto 36
35: iconst_0
36: invokevirtual #41; //Method java/io/PrintStream.println:(Z)V
39: return
String+String的操作是在运行时进行的,则会产生新的对象,而不是直接从jvm的string池中获取。
===============================
再看下面两个例子:
String a = "ab";
final String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //result = true
String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println((a == b)); //result = false
private static String getBB() {
return "b";
}
查看下面的字节码如下:
0: ldc #16; //String ab
2: astore_1
3: invokestatic #18; //Method getBB:()Ljava/lang/String;
6: astore_2
7: new #22; //class java/lang/StringBuilder
10: dup
11: ldc #24; //String a
13: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
16: aload_2
17: invokevirtual #29; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #33; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: astore_3
24: getstatic #36; //Field java/lang/System.out:Ljava/io/PrintStream;
27: aload_1
28: aload_3
29: if_acmpne 36
32: iconst_1
33: goto 37
36: iconst_0
37: invokevirtual #42; //Method java/io/PrintStream.println:(Z)V
40: return
分析:0: ldc #16; //String ab 变量a的值直接指向常量池中的‘ab’,
通过下面的分析可知 变量2通过StringBuilder进行string操作。
String a = "ab";
String b = "a" + "b";
System.out.println((a == b)); //它的执行结果为true;
2.下面这段代码的执行结果是什么?
String a = "ab";
String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //执行结果为false
以上两个执行结果的原因分析:
String b = "a" + "b";编译器将这个"a" + "b"作为常量表达式,在编译时进行优化,直接取结果"ab",这样这个问题退化
String a = "ab";
String b = "ab";
System.out.println((a == b));
然后根据3的解释,得到结果true
javap工具执行查看字节码如下:
0: ldc #16; //String ab
2: astore_1
3: ldc #16; //String ab
5: astore_2
6: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_1
10: aload_2
11: if_acmpne 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokevirtual #24; //Method java/io/PrintStream.println:(Z)V
22: return
通过 0: ldc #16; //String ab和 3: ldc #16; //String ab ,知道该java文件通过编译器编译后都变为 String b = "ab"; 和作者分析的一样。
===========================
对于第二个程序这个好理解,"a" + bb中的bb是变量,不能进行优化。javap查看字节码如下:
0: ldc #16; //String ab
2: astore_1
3: ldc #18; //String b
5: astore_2
6: new #20; //class java/lang/StringBuilder
9: dup
10: ldc #22; //String a
12: invokespecial #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
15: aload_2
16: invokevirtual #27; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #31; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_3
23: getstatic #35; //Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_1
27: aload_3
28: if_acmpne 35
31: iconst_1
32: goto 36
35: iconst_0
36: invokevirtual #41; //Method java/io/PrintStream.println:(Z)V
39: return
String+String的操作是在运行时进行的,则会产生新的对象,而不是直接从jvm的string池中获取。
===============================
再看下面两个例子:
String a = "ab";
final String bb = "b";
String b = "a" + bb;
System.out.println((a == b)); //result = true
String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println((a == b)); //result = false
private static String getBB() {
return "b";
}
查看下面的字节码如下:
0: ldc #16; //String ab
2: astore_1
3: invokestatic #18; //Method getBB:()Ljava/lang/String;
6: astore_2
7: new #22; //class java/lang/StringBuilder
10: dup
11: ldc #24; //String a
13: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
16: aload_2
17: invokevirtual #29; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: invokevirtual #33; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: astore_3
24: getstatic #36; //Field java/lang/System.out:Ljava/io/PrintStream;
27: aload_1
28: aload_3
29: if_acmpne 36
32: iconst_1
33: goto 37
36: iconst_0
37: invokevirtual #42; //Method java/io/PrintStream.println:(Z)V
40: return
分析:0: ldc #16; //String ab 变量a的值直接指向常量池中的‘ab’,
通过下面的分析可知 变量2通过StringBuilder进行string操作。