標籤:java 比較
首先來說下兩種比較符的使用情境:
1、==是一般用來比較實值型別,比較兩個資料類型的值是否相等,例如:byte,shot,char,int,long,float,double,boolean,實值型別(還有對象引用)一般儲存在記憶體的棧中
2、equals用來比較複合資料型別,複合資料型別的變數在棧中儲存的是參考型別變數的地址,本身儲存在堆中。
當使用==比較複合資料型別時,比較的是他們在記憶體中的地址,使用同一個new出來的是相等,否則不相等。
JAVA當中所有的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行為是比較對象的記憶體地 址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date在這些類當中equals有其自身的實現,而不再是比較類在堆記憶體中的存放地址了。
每new一個Object他們的記憶體位址不相同。
下面先貼一下String的equals的源碼看下:
/** * Compares this string to the specified object. The result is {@code * true} if and only if the argument is not {@code null} and is a {@code * String} object that represents the same sequence of characters as this * object. * * @param anObject * The object to compare this {@code String} against * * @return {@code true} if the given object represents a {@code String} * equivalent to this string, {@code false} otherwise * * @see #compareTo(String) * @see #equalsIgnoreCase(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; }
Object下即未被重寫過的equals方法:
public boolean equals(Object obj) { return (this == obj); }
比較實質:
在JAVA中利用”==”比較變數時,系統使用變數在”棧”中所存的值作為比較的依據。
基礎資料型別 (Elementary Data Type)在”棧”中存的是其內容值,而物件類型在”棧”中存的是地址,這些地址指向”堆”中的對象。
java.lang包中的Object類有public boolean equals(Object obj)方法,它比較兩個對象(hashcode)是否相等。
其它對象的equals方法僅當被比較的兩個引用指向的對象內容相同時,對象的equals()方法返回true。
總之,”==”和”!=”比較的是地址.也可認為”==”和”!=”比較的是物件控點;而equals()比較的是對象內容.或者說,,”==”和”!=”比較的是”棧”中的內容,而equals()比較的是”堆”中的內容.
publicclass Test{publicstaticvoid main(String[] args) { String s1 ="null"; String s2 =new String("null"); System.out.println(s1==s2);//false s2 = s2.intern(); System.out.println(s1==s2);//true}
(java.lang.String的intern()方法”abc”.intern()方法的傳回值還是字串”abc”,表面上看起來好像這個方 法沒什麼用處。但實際上,它做了個小動作:檢查字串池裡是否存在”abc”這麼一個字串,如果存在,就返回池裡的字串;如果不存在,該方法會 把”abc”添加到字串池中,然後再返回它的引用。
下面來看一個特殊的比較:
Integer i1 = 127; Integer j1 = 127; System.out.println(i1 == j1); // true Integer i2 = 128; Integer j2 = 128; System.out.println(i2 == j2);// false
以上是靠整型數的自動拆裝箱實現的,而兩者的結果卻不相同。
原因在於,在進行自動拆裝箱時,編譯器會使用Integer.valueof()來建立Integer執行個體。
先看一下源碼:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
如果傳入的int在IntegerCache.low和IntegerCache.high之間,那就嘗試看前面的緩衝中有沒有打過包的相同的值,如果有就直接返回,否則就建立一個Integer執行個體。IntegerCache.low 預設是-128;IntegerCache.high預設是127.
註:如果要比較兩個對象的內容是否相同,盡量不使用== 或者!= 來比較,可以使用equal()來實現。
Java中==和equals區別詳解