String物件是不可變的,String物件的其它API返回的String都是new出來的
本文從ByteCode角度解析使用==比較兩個String物件時的情況
工具/原料
IntelliJ IDEA
javap
方法/步驟
先來一段腳手架程式碼
Code:
package chapter5;
/**
* Created by MyWorld on 2016/4/3.
*/
public class StringStudyByByteCode {
public static void main(String[] args) {
String var1 = "StringByByteCode";
String var2 = "StringByByteCode";
System.out.println("var1==var2 :" + (var1 == var2));
}
}
Output:
執行結果:
var1==var2 :true
可以執行結果是true
現在從位元組碼角度來分析一下返回true的原因
使用javac來編譯剛才的.java檔案
命令:
javac chapter5/StringStudyByByteCode.java
使用javap來反編譯剛才生成的.class檔案
命令:
javap -v chapter5/StringStudyByByteCode
來找找程式碼中定義的兩個變數var1和var2
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=3, args_size=1
0: ldc #2 // String StringByByteCode
解釋://將#2對應的常量值載入到運算元棧棧頂
//可以看來#2對應的常量值就是“StringByByteCode”
2: astore_1 解釋://將當前運算元棧棧頂的資料賦於變數1,即var1
3: ldc #2 // String StringByByteCode
解釋://將#2對應的常量值載入到運算元棧棧頂
//可以看來#2對應的常量值就是“StringByByteCode”
5: astore_2 解釋://將當前運算元棧棧頂的資料賦於變數2,即var2
6: getstatic #3 // Field java/lang/System.out:
來看看常量值的#2對應的值是什麼
可以看到常量池中#2的值來自#27
反編譯程式碼中關於#2的資訊:
public class chapter5.StringStudyByByteCode
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #12.#26 // java/lang/Object."
#2 = String #27 // StringByByteCode
常量值#27對應的值是什麼
可以看到常量池中#27的值為“StringByByteCode”
反編譯程式碼中關於#27的資訊:
#26 = NameAndType #13:#14 // "
#27 = Utf8 StringByByteCode
#28 = Class #42 // java/lang/System
通過上面的分析,可以看到
變數var1和var2的值都來自常量池中的#2
對物件使用==操作符時,比較的是記憶體地址
這種情況下,var1==var2就應該是true了