二話不說,先來說下重寫的事情:
在Java中,String 、Math、還有Integer、Double。。。。等這些封裝類重寫了Object中的equals()方法,讓它不再比較其對象在內存中的地址,而是比較對象中實際包含的整數的值,即比較的是內容。
再強調一次,Object的equals()方法比較的是地址值,所以Object equals相等時,其hashcode必然相等,因為都是對象的地址,所以自己定義的類如果要加入到集合類中一定要記得重寫這兩個方法。
在Eclipse中重寫hashcode和equals方法使相當方便的,只需要右鍵->source->Generate hashcode() and equals()便可以了
意思是 :非Object聲明的對象,都已經重寫了equals方法,不需要我們自己重寫了。,Object聲明的必須重寫才可以比較內容。而非地址。
對於 數值型的,我們就用==比較,對於其他類型的,自己選擇,建議我們可以用使用Stringutils來避免空指針的問題。
對於String中的“equal方法”和“==”一直有點混餚,今天重新看了一下他們兩點的區別,記錄下來讓自己以后不在忘記!
"=="和equals方法究竟有什么區別?
(單獨把一個東西說清楚,然后再說清楚另一個,這樣,它們的區別自然就出來了,混在一起說,則很難說清楚)
==操作符專門用來比較兩個變量的值是否相等,也就是用於比較變量所對應的內存中所存儲的數值是否相同,要比較兩個基本類型的數據或兩個引用變量是否相等,只能用==操作符。
如果一個變量指向的數據是對象類型的,那么,這時候涉及了兩塊內存,對象本身占用一塊內存(堆內存),變量也占用一塊內存,例如Objet obj = newObject();變量obj是一個內存,new Object()是另一個內存,此時,變量obj所對應的內存中存儲的數值就是對象占用的那塊內存的首地址。對於指向對象類型的變量,如果要比較兩個變量是否指向同一個對象,即要看這兩個變量所對應的內存中的數值是否相等,這時候就需要用==操作符進行比較。
equals方法是用於比較兩個獨立對象的內容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨立的。例如,對於下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創建了兩個對象,然后用a/b這兩個變量分別指向了其中一個對象,這是兩個不同的對象,它們的首地址是不同的,即a和b中存儲的數值是不相同的,所以,表達式a==b將返回false,而這兩個對象中的內容是相同的,所以,表達式a.equals(b)將返回true。
在實際開發中,我們經常要比較傳遞進行來的字符串內容是否等,例如,String input = …;input.equals(“quit”),許多人稍不注意就使用==進行比較了,這是錯誤的,隨便從網上找幾個項目實戰的教學視頻看看,里面就有大量這樣的錯誤。記住,字符串的比較基本上都是使用equals方法。
如果一個類沒有自己定義equals方法,那么它將繼承Object類的equals方法,Object類的equals方法的實現代碼如下:
boolean equals(Object o){
return this==o;
}
這說明,如果一個類沒有自己定義equals方法,它默認的equals方法(從Object類繼承的)就是使用==操作符,也是在比較兩個變量指向的對象是否是同一對象,這時候使用equals和使用==會得到同樣的結果,如果比較的是兩個獨立的對象則總返回false。如果你編寫的類希望能夠比較該類創建的兩個實例對象的內容是否相同,那么你必須覆蓋equals方法,由你自己寫代碼來決定在什么情況即可認為兩個對象的內容是相同的。
-----------------------------------------------------------------
簡單的說,==比較兩個人是否究竟是真正同一個人,equals一般用來比較兩個人在邏輯上是否相等(比如規定兩人成年之后身高相同就算兩人相同等等),想怎么定義就怎么定義,如果不覆蓋equals方法的話,默認仍然是比較兩人是否同一個人(廢話,兩個人都還處於胚胎狀態,都沒有具體特征,怎么可能在邏輯上比較)。
先說“==”:
“==”是用來比較兩個String對象在內存中的存放地址是否相同的。例如,
|
1
2
3
4
5
6
7
8
9
|
String test1 =
"test"
;
String test2 =
"test"
;
String test3 =
new
String(test2);
String test4 =
new
String(test2);
blooean result1 = (test1==test2);
blooean result2 = (test3==test4);
|
其中:result1為true,result2為false。
原因:程序在運行時有一個字符串緩存機制,當String test1 = "test"的時候,程序先從緩存池中查找是否有相同的String 對象,如果有的話就不會重新生成而是用緩存池中的字符串對象;如果在字符串緩存池中沒找到相同的字符串對象時才會在內存中開辟一塊內存區新建字符串對象。對於test1,當test1建立以后會將“test”字符串放入緩存池中,所以運行 String test2 = "test"的時候就會直接從緩存池中取出相同的對象,也就說,test1和test2的內存地址是相同的,所以,result1是true。對於new來說,每new一次就會在內存中開辟一片內存區域,test3和test4的內存地址是不同的,所以result2是false。
再說“equal方法”:
equal方法是object類的方法,object類中的equal方法也使用“==”實現的,也就是說,如果直接繼承object類的equal方法,則也是比較兩個對象在內存中的地址是否相同,但是在String中將繼承自object的equal方法覆蓋啦!String中的equal方法源碼如下:
1 /**
2 * Compares this string to the specified object. The result is {@code
3 * true} if and only if the argument is not {@code null} and is a {@code
4 * String} object that represents the same sequence of characters as this
5 * object.
6 *
7 * @param anObject
8 * The object to compare this {@code String} against
9 *
10 * @return {@code true} if the given object represents a {@code String}
11 * equivalent to this string, {@code false} otherwise
12 *
13 * @see #compareTo(String)
14 * @see #equalsIgnoreCase(String)
15 */
16 public boolean equals(Object anObject) {
17 if (this == anObject) {
18 return true;
19 }
20 if (anObject instanceof String) {
21 String anotherString = (String) anObject;
22 int n = value.length;
23 if (n == anotherString.value.length) {
24 char v1[] = value;
25 char v2[] = anotherString.value;
26 int i = 0;
27 while (n-- != 0) {
28 if (v1[i] != v2[i])
29 return false;
30 i++;
31 }
32 return true;
33 }
34 }
35 return false;
36 }
可以看出:在String中的equal方法是比較兩個String對象的內容是否相同。
java中的equals與==?
在初學Java時,可能會經常碰到下面的代碼:
1 String str1 = new String("hello");
2 String str2 = new String("hello");
3
4 System.out.println(str1==str2);
5 System.out.println(str1.equals(str2));
為什么第4行和第5行的輸出結果不一樣?==和equals方法之間的區別是什么?如果在初學Java的時候這個問題不弄清楚,就會導致自己在以后編寫代碼時出現一些低級的錯誤。今天就來一起了解一下==和equals方法的區別之處。
一.關系操作符“==”到底比較的是什么?
下面這個句話是摘自《Java編程思想》一書中的原話:
“關系操作符生成的是一個boolean結果,它們計算的是操作數的值之間的關系”。
這句話看似簡單,理解起來還是需要細細體會的。說的簡單點,==就是用來比較值是否相等。下面先看幾個例子:
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=3;
int m=3;
System.out.println(n==m);
String str = new String("hello");
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1==str2);
str1 = str;
str2 = str;
System.out.println(str1==str2);
}
}
輸出結果為 true false true
n==m結果為true,這個很容易理解,變量n和變量m存儲的值都為3,肯定是相等的。而為什么str1和str2兩次比較的結果不同?要理解這個其實只需要理解基本數據類型變量和非基本數據類型變量的區別。
在Java中游8種基本數據類型:
浮點型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
字符型: char(2 byte)
布爾型: boolean(JVM規范沒有明確規定其所占的空間大小,僅規定其只能夠取字面值"true"和"false")
對於這8種基本數據類型的變量,變量直接存儲的是“值”,因此在用關系操作符==來進行比較時,比較的就是 “值” 本身。要注意浮點型和整型都是有符號類型的,而char是無符號類型的(char類型取值范圍為0~2^16-1).
也就是說比如:
int n=3;
int m=3;
變量n和變量m都是直接存儲的"3"這個數值,所以用==比較的時候結果是true。
而對於非基本數據類型的變量,在一些書籍中稱作為 引用類型的變量。比如上面的str1就是引用類型的變量,引用類型的變量存儲的並不是 “值”本身,而是於其關聯的對象在內存中的地址。比如下面這行代碼:
String str1;
這句話聲明了一個引用類型的變量,此時它並沒有和任何對象關聯。
而 通過new String("hello")來產生一個對象(也稱作為類String的一個實例),並將這個對象和str1進行綁定:
str1= new String("hello");
那么str1指向了一個對象(很多地方也把str1稱作為對象的引用),此時變量str1中存儲的是它指向的對象在內存中的存儲地址,並不是“值”本身,也就是說並不是直接存儲的字符串"hello"。這里面的引用和C/C++中的指針很類似。
因此在用==對str1和str2進行第一次比較時,得到的結果是false。因此它們分別指向的是不同的對象,也就是說它們實際存儲的內存地址不同。
而在第二次比較時,都讓str1和str2指向了str指向的對象,那么得到的結果毫無疑問是true。
二.equals比較的又是什么?
equals方法是基類Object中的方法,因此對於所有的繼承於Object的類都會有該方法。為了更直觀地理解equals方法的作用,直接看Object類中equals方法的實現。
該類的源碼路徑為:C:\Program Files\Java\jdk1.6.0_14的src.zip 的java.lang路徑下的Object.java(視個人jdk安裝路徑而定)。
下面是Object類中equals方法的實現:

很顯然,在Object類中,equals方法是用來比較兩個對象的引用是否相等,即是否指向同一個對象。
但是有些朋友又會有疑問了,為什么下面一段代碼的輸出結果是true?
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2));
}
}
要知道究竟,可以看一下String類的equals方法的具體實現,同樣在該路徑下,String.java為String類的實現。
下面是String類中equals方法的具體實現:

可以看出,String類對equals方法進行了重寫,用來比較指向的字符串對象所存儲的字符串是否相等。
其他的一些類諸如Double,Date,Integer等,都對equals方法進行了重寫用來比較指向的對象所存儲的內容是否相等。
總結來說:
1)對於==,如果作用於基本數據類型的變量,則直接比較其存儲的 “值”是否相等;
如果作用於引用類型的變量,則比較的是所指向的對象的地址
2)對於equals方法,注意:equals方法不能作用於基本數據類型的變量
如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址;
諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的對象的內容

