1:基本數據類型
又稱為原始數據類型,他們之間的比較應該使用(==),比較的是他們的值。
2:引用數據類型
當引用數據類型用(==)進行比較,比較的是他們在內存中的存放地址。
當復合數據類型之間進行equals比較時,這個方法的初始行為是比較對象在堆內存中的地址。
equals()方法是用來判斷其他的對象是否和該對象相等.


但在一些諸如String,Integer,Date類中把Object中的這個方法覆蓋了,作用被覆蓋為比較內容是否相同。

很明顯,這是進行的內容比較,而已經不再是地址的比較。依次類推Math、Integer、Double等這些類都是重寫了equals()方法的,從而進行的是內容的比較。當然,基本類型是進行值的比較。
二: String類的討論
輸出true
說明:==在進行復合數據類型比較時,比較的是內存中的存放地址。因此a與b引用同一個String對象。
輸出:
false
true
說明:b,c分別引用了兩個對象。顯然,兩者內容是相同的,因此equal返回true。第一個例子也一樣。
三: 解釋
首先看一張內存上述的內存分配圖
從圖中可以發現每個String對象的內容實際是保存到堆內存中的,而且堆中的內容是相等的,但是對於str1和str2來說所指向的地址堆內存地址是不等的,所以盡管內容是相等的,但是地址值是不相等的
“==”是用來進行數值比較的,所以str1和str2比較不相等,因為str2和str3指向同一個內存地址所以str2和str3是相等的。所以“==”是用來進行地址值比較的。
5. 為什么Java中1000==1000為false而100==100為true?
查看Integer.java類,會發現有一個內部私有類,IntegerCache.java,它緩存了從-128到127之間的所有的整數對象。
============================================================================================================================================================
Hashcode的作用
想要明白,必須要先知道Java中的集合。
總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。前者集合內的元素是有序的,元素可以重復;后者元素無序,但元素不可重復。
那么這里就有一個比較嚴重的問題了:要想保證元素不重復,可兩個元素是否重復應該依據什么來判斷呢?
這就是Object.equals方法了。但是,如果每增加一個元素就檢查一次,那么當元素很多時,后添加到集合中的元素比較的次數就非常多了。也就是說,如果集合中現在已經有1000個元素,那么第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大降低效率。
於是,Java采用了哈希表的原理。
這樣一來,當集合要添加新的元素時,
先調用這個元素的hashCode方法,就一下子能定位到它應該放置的物理位置上。
如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;
如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存,不相同就散列其它的地址。所以這里存在一個沖突解決的問題。這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。
4、eqauls方法和hashCode方法關系
Java對於eqauls方法和hashCode方法是這樣規定的:
(1)同一對象上多次調用hashCode()方法,總是返回相同的整型值。
(2)如果a.equals(b),則一定有a.hashCode() 一定等於 b.hashCode()。
(3)如果!a.equals(b),則a.hashCode() 不一定等於 b.hashCode()。此時如果a.hashCode() 總是不等於 b.hashCode(),會提高hashtables的性能。
(4)a.hashCode()==b.hashCode() 則 a.equals(b)可真可假
(5)a.hashCode()!= b.hashCode() 則 a.equals(b)為假。
上面結論簡記:
1、如果兩個對象equals,Java運行時環境會認為他們的hashcode一定相等。
2、如果兩個對象不equals,他們的hashcode有可能相等。
3、如果兩個對象hashcode相等,他們不一定equals。
4、如果兩個對象hashcode不相等,他們一定不equals。
關於這兩個方法的重要規范:
規范1:若重寫equals(Object obj)方法,有必要重寫hashcode()方法,確保通過equals(Object obj)方法判斷結果為true的兩個對象具備相等的hashcode()返回值。說得簡單點就是:“如果兩個對象相同,那么他們的hashcode應該相等”。不過請注意:這個只是規范,如果你非要寫一個類讓equals(Object obj)返回true而hashcode()返回兩個不相等的值,編譯和運行都是不會報錯的。不過這樣違反了Java規范,程序也就埋下了BUG。
規范2:如果equals(Object obj)返回false,即兩個對象“不相同”,並不要求對這兩個對象調用hashcode()方法得到兩個不相同的數。說的簡單點就是:“如果兩個對象不相同,他們的hashcode可能相同”。
5、為什么覆蓋equals時總要覆蓋hashCode
一個很常見的錯誤根源在於沒有覆蓋hashCode方法。在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法。如果不這樣做的話,就會違反Object.hashCode的通用約定,從而導致該類無法結合所有基於散列的集合一起正常運作,這樣的集合包括HashMap、HashSet和Hashtable。
1.在應用程序的執行期間,只要對象的equals方法的比較操作所用到的信息沒有被修改,那么對這同一個對象調用多次,hashCode方法都必須始終如一地返回同一個整數。在同一個應用程序的多次執行過程中,每次執行所返回的整數可以不一致。
2.如果兩個對象根據equals()方法比較是相等的,那么調用這兩個對象中任意一個對象的hashCode方法都必須產生同樣的整數結果。
3.如果兩個對象根據equals()方法比較是不相等的,那么調用這兩個對象中任意一個對象的hashCode方法,則不一定要產生相同的整數結果。但是程序員應該知道,給不相等的對象產生截然不同的整數結果,有可能提高散列表的性能。
6、總結:
1、equals方法用於比較對象的內容是否相等(覆蓋以后)
2、hashcode方法只有在集合中用到
3、當覆蓋了equals方法時,比較對象是否相等將通過覆蓋后的equals方法進行比較(判斷對象的內容是否相等)。
4、將對象放入到集合中時,首先判斷要放入對象的hashcode值與集合中的任意一個元素的hashcode值是否相等,如果不相等直接將該對象放入集合中。如果hashcode值相等,然后再通過equals方法判斷要放入對象與集合中的任意一個對象是否相等,如果equals判斷不相等,直接將該元素放入到集合中,否則不放入。
===========================================================================================================================
===========================================================================================================================
===========================================================================================================================
===========================================================================================================================
===========================================================================================================================
1)判斷String類型的 s1 和 s2 是否相等

equals() 方法比較的是字符串的內容~所以結果是 true 很好理解,至於 str1==str2 的結果也是 true ,是因為在 Java 的內存的方法區中有一塊區域叫做常量池,str1 =“abc” 時,常量池中沒有 “abc”,所以就 new 一個 “abc” 當運行 str2 = “abc” 時,常量池中存在 “abc” ,系統就會把 常量池中的 “abc” 的引用直接給 str2 所以 str1==str2 的結果為 true,因為它們的引用是一樣的~
2)判斷String類型的 s1 和 s2 是否相等

這個和上一題很像,但是 str1 是 new string() ,在 Java 中,new 一個對象就會在內存的堆中開辟一塊空間,然后把引用賦值給 str1 ,一個是堆中的引用,一個是常量池中的引用所以,str1==str2 的結果為 false~~
3)判斷String類型的 s1 和 s2 是否相等

這個 str1==str2 為何為 true 小伙伴們知道嗎?嘿嘿因為在Java中有一種叫做常量優化的機制,我們在賦值的時候 “a”,“b”,“c”都是常量,系統及直接把 abc 賦值給 str1 了,這時候常量池中也就存在 “abc” 了,所以str1==str2
4)判斷String類型的 s1 和 s2 是否相等

那么這里呢?通過查找API我們可以得到這樣一段話~ 『Java 語言提供對字符串串聯符號("+")以及將其他對象轉換為字符串的特殊支持。字符串串聯是通過 StringBuilder(或 StringBuffer)類及其 append 方法實現的。字符串轉換是通過 toString 方法實現的...』
也就是說當執行 str3=str1+c 的時候,首先在堆中生成一個StringBuilder(或StringBuffer)對象,然后把 ab 和 c 連接在一起 ,再利用 toString 方法生成一個 “abc”的字符串 再來進行比較..str2 的 “abc” 在常量池中,str3 在堆中所以為false~