java String 類equals方法和==的比較
最近在通過閱讀《深入理解Java虛擬機器——JVM特性與最佳實踐》這本書時,發現書中在介紹執行時常量池中有這樣一段話:
“執行時常量池相對於Class檔案常量池的另外一個重要特徵是具備動態性,Java語言並要求常量一定只有編譯期才能產生,也就是並非預置入Class檔案中常量池的內容才能進入方法區執行時常量池,執行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較多得是String類的intern()方法”
intern()方法在jdk的文件中是這樣描述的:“When the intern method is invoked, if the pool already contains a string equal to this {@code String} object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, this {@code String} object is added to the pool and a reference to this {@code String} object is returned.”簡而言之,如果池中有該變數即引用,沒有就建立。
在驗證之前,要了解一下“==” 和 equals方法的區別:
Java有八大基礎型別分別是:byte, short, char, int, long, float, double, boolean
上述資料型別沒有equals方法,==方法就是比較資料的值是否相等
而對於其他複合資料型別而言,==方法是比較兩個物件的引用是否相等,也就是比較兩個物件的地址是否相等(是不是同一個物件),眾所周知所有java型別都有個公共的爹,Object類,而在該類中也定義了一個equals方法
public boolean equals(Object obj) { return (this == obj); }
可以看到該方法就是呼叫了==方法即比較兩個物件的地址值是否相等,String類中對該類進行了重寫,
在該方法中,首先判斷是否為同一個物件,如果不是同一個物件,那麼判斷是否為String型別,如果不為String型別就返回false,如果為String型別將其轉換為基本資料型別char,通過基本資料型別的比較為值比較來比較兩個String物件的值是否相等。public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
下面的程式碼可以驗證:
String str0 = new String("a");
String str1 = str0.intern();
String str2 = "a";
String str3 = "a";
System.out.println(str1 == str0);//false
System.out.println(str2 == str0);//false
System.out.println(str2 == str1);//true
System.out.println(str3 == str2);//true
以上物件的比較如果通過equals方法返回值都為true