檢視位元組碼 javap -v xxx.class
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hel" + "lo";
String s3 = new String("Hello");
String s4 = "Hel" + new String("lo");
String s5 = s3.intern();
int i1 = 0;
int i2 = 1;
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
System.out.println(s2 == s4);
System.out.println(s1 == s2);
System.out.println(s2 == s5);
System.out.println(i1 == i2);
}
Constant pool:(常量池)
#2 = String #36 // Hello
#3 = Class #37 // java/lang/String
#5 = Class #39 // java/lang/StringBuilder
#7 = String #40 // Hel
#9 = String #42 // lo
{
stack=4, locals=8, args_size=1
0: ldc #2 // String Hello (載入常量池的#2號字串壓入棧)
2: astore_1 (將上一步載入的引用變數賦值給變數1,即s1【參照LocalVariableTable的slot數值】)
3: ldc #2 // String Hello (載入常量池的#2號字串壓入棧)
5: astore_2 (將上一步載入的引用變數賦值給變數2,即s2【參照LocalVariableTable的slot數值】)
6: new #3 // class java/lang/String (建立#3號的例項:java/lang/String)
9: dup (複製上一步建立的物件的引用壓入棧)
10: ldc #2 // String Hello (載入常量池的#2號字串壓入棧)
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V (呼叫String的init方法,將上一步載入入棧的引用作為引數傳入init方法)
15: astore_3 (將上一步返回的引用變數賦值給變數3,即s3【參照LocalVariableTable的slot數值】)
16: new #5 // class java/lang/StringBuilder(建立#5號的例項:java/lang/StringBuilder)
19: dup (複製上一步建立的物件引用壓入棧)
20: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V (呼叫StringBuilder的init方法)
23: ldc #7 // String Hel (載入常量池#7號字串壓入棧)
25: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; (呼叫StringBuilder的append方法,將上一步載入的引用作為引數傳入append方法)
28: new #3 // class java/lang/String (建立#3號的例項:java/lang/String)
31: dup (複製上一步建立的物件的引用壓入棧)
32: ldc #9 // String lo (載入常量池#9號字串壓入棧)
34: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V (呼叫String的init方法,將上一步載入入棧的引用作為引數傳入init方法)
37: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; (呼叫StringBuilder的append方法,將上一步載入的引用作為引數傳入append方法)
40: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;(呼叫StringBuilder的toString方法)
43: astore 4 (將上一步返回的引用賦值給變數4,即s4【參照LocalVariableTable的slot數值】)
45: aload_3 (載入變數3壓入棧)
46: invokevirtual #11 // Method java/lang/String.intern:()Ljava/lang/String; (呼叫String的intern方法)
49: astore 5 (將上一步返回的引用賦值給變數5,即s5【參照LocalVariableTable的slot數值】)
51: iconst_0 (將數字0壓入棧)
52: istore 6 (將上一步載入的數字賦值給變數6,即i1【參照LocalVariableTable的slot數值】)
54: iconst_1 (將數字1壓入棧)
55: istore 7 (將上一步載入的數字賦值給變數7,即i2【參照LocalVariableTable的slot數值】)
57: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; (呼叫System的靜態方法out)
60: aload_1 (載入變數1,即s1)
61: aload_2 (載入變數2,即s2)
62: if_acmpne 69(比較s1和s2是否不相等,如果不相等,跳轉到63行指令,如果相等則繼續下一步,if_acmpne和if_icmpne,a表示物件引用比較,I表示數字比較;if_acmpeq和if_acmpne,eq【equal】表示相等,ne【not equal】)
65: iconst_1 (將數字1壓入棧)
66: goto 70 (跳轉到64行指令)
69: iconst_0 (將數字0壓入棧)
70: invokevirtual #13 // Method java/io/PrintStream.println:(Z)V
……
156: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream;
159: iload 6 (載入變數6,即i1)
161: iload 7 (載入變數7,即i2)
163: if_icmpne 170(比較i1和i2)
166: iconst_1
167: goto 171
170: iconst_0
171: invokevirtual #13 // Method java/io/PrintStream.println:(Z)V
……
150: return
LocalVariableTable:
Start Length Slot Name Signature
0 151 0 args [Ljava/lang/String;
3 148 1 s1 Ljava/lang/String;
6 145 2 s2 Ljava/lang/String;
16 135 3 s3 Ljava/lang/String;
45 106 4 s4 Ljava/lang/String;
51 100 5 s5 Ljava/lang/String;
54 121 6 i1 I
57 118 7 i2 I
}