[英]How does the toString(), ==, equals() object methods work differently or similarly on reference and primitive types?
toString()
方法, ==
運算符和equals()
方法如何在引用和基元類型上以不同或相似的方式工作?
對於常規類型(包括String):
==
比較對象引用。 它測試兩個對象引用是否相等; 即如果他們引用同一個對象。 equals(Object)
測試此對象是否“等於”另一個對象。 “等於”意味着取決於對象的類如何定義相等性。 java.lang.Object
類將equals(other)
定義為this == other
,但許多類重寫此定義。 toString()
提供了對象到String的簡單轉換。 結果String的格式和內容是特定於類的,並且(從java.lang.Object
契約的角度來看)不能保證它有意義。 對於(真)原始類型:
==
比較類型的值,和 equals()
和toString()
。 Java不允許您在原始值上調用方法。 然而,由於在某些情況下 Java語言表示原始類型可以“自動裝箱”以給出基本類型的相應包裝類型的實例,因此這很復雜。 例如, int
對應於java.lang.Integer
,依此類推。 對於包裝類:
==
的定義與任何其他引用類型相同, equals()
比較包裝的值,和 toString()
格式化包裝的值。 工程中的扳手如下圖所示:
int a = ...
int b = a;
Integer aa = a; // autoboxing occurs
Integer bb = b; // autoboxing occurs
assert a == b; // always succeeds
assert aa.equals(bb); // always succeeds
assert aa == bb; // sometimes succeeds, sometimes fails.
最后一次失敗的原因是JLS不保證給定原始值的自動裝箱將始終給出相同的包裝器對象。 它在某些情況下(例如小整數),而不會用於其他情況(例如大整數)。
從上面的示例中學到的教訓是,在引用類型上使用==
時需要非常小心。 只有當你真的要測試兩個引用是否屬於同一個對象時才使用它。 如果您只想測試對象是否“相等”而沒有調用equals()
的開銷,請不要使用它。
(另請注意, String
是另一種類型,其中==
在許多情況下會給你錯誤的答案;請參閱如何比較Java中的字符串? )
對於引用類型,==將比較實際引用(對象所在的內存位置),其中equals方法執行數據比較。
出於性能原因,JVM有時會“字符串實例化”您的不可變字符串。 導致這種情況:
String a = "abc";
String b = "abc";
if (a == b){
//The if statement will evaluate to true,
//if your JVM string interns a and b,
//otherwise, it evaluates to false.
}
'=='運算符適用於您擁有的基本類型,在引用對象的情況下,它是引用本身。 這是a == b
會將原始類型的值作為int進行比較,但會比較引用類型的引用(而不是值)。 兩個引用類型不同但具有相同值的對象將在調用equals()
方法時返回true
,但a == b
將為false。
對於基本類型,在調用方法時,類型先前被轉換(加框)為引用類型,然后調用該方法。 這意味着對於基本類型, a == b
將產生與a.equals(b)
相同的值,但在后一種情況下,在調用equals()
方法之前會創建兩個臨時的盒裝對象。 這將使CPU操作中的操作更加昂貴,這可能是也可能不是問題,這取決於它發生的位置。
也就是說,要比較基本類型值,您應該使用==
,而要比較引用類型值,您應該使用.equals()
方法。
toString()
方法也是如此。 在引用類型對象上調用時,它將調用適當的方法並生成一個String。 當調用基本類型時,類型將被自動裝箱,然后將在臨時對象中調用該方法。 在這種情況下,您可以調用相應的toString()
靜態方法(即對於int調用Integer.toString( myint )
),這將避免創建臨時對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.