62,635
社区成员




String a = "hello2";
final String b = "hello";
String c = "hello";
System.out.println(a==(b+2));
System.out.println(a==(c+2));
public cn.wxy.enumm.Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/wxy/enumm/Main;
public static void main(java.lang.String[])
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=4, args_size=1
0: ldc #16 // String hello2
2: astore_1
3: ldc #18 // String hello
5: astore_2
6: ldc #18 // String hello
8: astore_3
9: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_1
13: ldc #16 // String hello2
15: if_acmpne 22
18: iconst_1
19: goto 23
22: iconst_0
23: invokevirtual #26 // Method java/io/PrintStream.println:(Z)V
26: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream;
29: aload_1
30: new #32 // class java/lang/StringBuilder
33: dup
34: aload_3
35: invokestatic #34 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
38: invokespecial #40 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
41: iconst_2
42: invokevirtual #43 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
45: invokevirtual #47 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
48: if_acmpne 55
51: iconst_1
52: goto 56
55: iconst_0
56: invokevirtual #26 // Method java/io/PrintStream.println:(Z)V
59: return
LineNumberTable:
line 13: 0
line 14: 3
line 15: 6
line 17: 9
line 18: 26
line 20: 59
LocalVariableTable:
Start Length Slot Name Signature
0 60 0 args [Ljava/lang/String;
3 57 1 a Ljava/lang/String;
6 54 2 b Ljava/lang/String;
9 51 3 c Ljava/lang/String;
[/quote]
忘了讲了,上面这个是楼主代码的编译后字节码,其实也就是虚拟机的执行步骤。
倒着讲:
1. 48、51、52、55的语义:a==(c+2),如果相等,则返回ture,否则返回false;
2. 从26到45都是为1的比较做准备,从局部变量表获取final b,iconst_2把2压运行时栈,然后new StringBuilder包起来;
3. 最后,a是直接从方法区常量池获取,而(c+2)则是等到运行时才能确定,直接从方法区中SB对象的toString方法获取,然后你比较地址,显然不相等。public cn.wxy.enumm.Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/wxy/enumm/Main;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=4, args_size=1
0: ldc #16 // String hello2
2: astore_1
3: ldc #18 // String hello
5: astore_2
6: ldc #18 // String hello
8: astore_3
9: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_1
13: ldc #16 // String hello2
15: if_acmpne 22
18: iconst_1
19: goto 23
22: iconst_0
23: invokevirtual #26 // Method java/io/PrintStream.println:(Z)V
26: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream;
29: aload_1
30: new #32 // class java/lang/StringBuilder
33: dup
34: aload_3
35: invokestatic #34 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
38: invokespecial #40 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
41: iconst_2
42: invokevirtual #43 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
45: invokevirtual #47 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
48: if_acmpne 55
51: iconst_1
52: goto 56
55: iconst_0
56: invokevirtual #26 // Method java/io/PrintStream.println:(Z)V
59: return
LineNumberTable:
line 13: 0
line 14: 3
line 15: 6
line 17: 9
line 18: 26
line 20: 59
LocalVariableTable:
Start Length Slot Name Signature
0 60 0 args [Ljava/lang/String;
3 57 1 a Ljava/lang/String;
6 54 2 b Ljava/lang/String;
9 51 3 c Ljava/lang/String;
private final char value[];
表明String不仅不能被复写,连它里面存数组的域都是final的,意思你一旦初始化它你就没法改它了
a==(b+2) 的理解同楼上
a==(c+2) ,c+2 会返回 new String("hello2")而不是在常量池里寻找出来的