考試大編輯整理第三篇Java雜記了,前兩次分別講述了關于jvm、jdk、jre、collection、classLoader和一些DesignPattern的自我理解。這次仍然不準備開始過渡到j2ee中,因為覺得還有一些瑣碎的j2se的問題沒有總結完畢。
1.關于Object類理解
大家都知道Object是所有Java類的基類,意味著所有的Java類都會繼承了Object的11個方法。建議大家去看看Object的11個成員函數的源代碼,就會知道默認的實現方式。比如equals方法,默認實現就是用"=="來比較,即直接比較內存地址,返回true或者false.而toString()方法,返回的串組成方式是??
"getClass()。getName()+"@"+Integer.toHexString(hashCode())"其實不用我過多的解釋,大家都能看懂這個串的組成。接下來再看看hashCode():publicnativeinthashCode();
由于是native方法,跟OS的處理方式相關,源代碼里僅僅有一個聲明罷了。我們有興趣的話完全可以去深究它的hashCode到底是由OS怎么樣產生的呢?但筆者建議重要的還是先記住使用它的幾條原則吧!首先如果equals()方法相同的對象具有相通的hashCode,但equals()對象不相通的時候并不保證hashCode()方法返回不同的整數。而且下運行同一個程序,同一個對象未必還是當初的那個hashCode()哦。
其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,說明依賴于操作系統(tǒng)的實現。后一個有趣的方法是finalize(),類似C++的析構函數,簽名是protected,證明只有繼承擴展了才能使用,方法體是空的,默示什么也不做。它的作用據筆者的了解僅僅是通知JVM此對象不再使用,隨時可以被銷毀,而實際的銷毀權還是在于虛擬機手上。那么它真的什么也不做麼?未必,實際上如果是線程對象它會導致在一定范圍內該線程的優(yōu)先級別提高,導致更快的被銷毀來節(jié)約內存提高性能。其實從常理來說,我們也可以大概這樣猜測出jvm做法的目的。
2.關于重載hashCode()與Collection框架的關系
筆者曾經聽一位搞Java培訓多年的前輩說在他看來hashCode方法沒有任何意義,僅僅是為了配合證明具有同樣的hashCode會導致equals方法相等而存在的。連有的前輩都犯這樣的錯誤,其實說明它還是滿容易被忽略的。那么hashCode()方法到底做什么用?
學過數據結構的課程大家都會知道有一種結構叫hashtable,目的是通過給每個對象分配一個的索引來提高查詢的效率。那么Java也不會肆意扭曲改變這個概念,所以hashCode的作用就是為支持數據結構中的哈希表結構而存在的,換句話說,也就是只有用到集合框架的Hashtable、HashMap、HashSet的時候,才需要重載hashCode()方法,這樣才能使得我們能人為的去控制在哈希結構中索引是否相等。筆者舉一個例子:曾經為了寫一個求解類程序,需要隨機列出1,2,3,4組成的不同排列組合,所以筆者寫了一個數組類用int[]來存組合結果,然后把隨機產生的組合加入一個HashSet中,就是想利用HashSet不包括重復元素的特點??墒荋ashSet怎么判斷是不是重復的元素呢?當然是通過hashCode()返回的結果是否相等來判斷啦,可做一下這個實驗:
int[]A={1,2,3,4};
int[]B={1,2,3,4};
System.out.println(A.hashCode());
System.out.println(B.hashCode());
這明明是同一種組合,卻是不同的hashCode,加入Set的時候會被當成不同的對象。這個時候我們就需要自己來重寫hashCode()方法了,如何寫呢?其實也是基于原始的hashCode(),畢竟那是操作系統(tǒng)的實現,找到相通對象的標識,實現方式很多,筆者的實現方式是:首先重寫了toString()方法:return A[0]“+”A[1]“+”A[2]“+”A[3];//顯示上比較直觀然后利用toString()來計算hashCode():return this.toString()。hashCode();這樣上述A和B返回的就都是“1234”,在測試toString()。hashCode(),由于String在內存中的副本是一樣的,“1234”。hashCode()返回的一定是相同的結果。
說到這,相信大家能理解得比我更好,今后千萬不要再誤解hashCode()方法的作用。
1.關于Object類理解
大家都知道Object是所有Java類的基類,意味著所有的Java類都會繼承了Object的11個方法。建議大家去看看Object的11個成員函數的源代碼,就會知道默認的實現方式。比如equals方法,默認實現就是用"=="來比較,即直接比較內存地址,返回true或者false.而toString()方法,返回的串組成方式是??
"getClass()。getName()+"@"+Integer.toHexString(hashCode())"其實不用我過多的解釋,大家都能看懂這個串的組成。接下來再看看hashCode():publicnativeinthashCode();
由于是native方法,跟OS的處理方式相關,源代碼里僅僅有一個聲明罷了。我們有興趣的話完全可以去深究它的hashCode到底是由OS怎么樣產生的呢?但筆者建議重要的還是先記住使用它的幾條原則吧!首先如果equals()方法相同的對象具有相通的hashCode,但equals()對象不相通的時候并不保證hashCode()方法返回不同的整數。而且下運行同一個程序,同一個對象未必還是當初的那個hashCode()哦。
其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,說明依賴于操作系統(tǒng)的實現。后一個有趣的方法是finalize(),類似C++的析構函數,簽名是protected,證明只有繼承擴展了才能使用,方法體是空的,默示什么也不做。它的作用據筆者的了解僅僅是通知JVM此對象不再使用,隨時可以被銷毀,而實際的銷毀權還是在于虛擬機手上。那么它真的什么也不做麼?未必,實際上如果是線程對象它會導致在一定范圍內該線程的優(yōu)先級別提高,導致更快的被銷毀來節(jié)約內存提高性能。其實從常理來說,我們也可以大概這樣猜測出jvm做法的目的。
2.關于重載hashCode()與Collection框架的關系
筆者曾經聽一位搞Java培訓多年的前輩說在他看來hashCode方法沒有任何意義,僅僅是為了配合證明具有同樣的hashCode會導致equals方法相等而存在的。連有的前輩都犯這樣的錯誤,其實說明它還是滿容易被忽略的。那么hashCode()方法到底做什么用?
學過數據結構的課程大家都會知道有一種結構叫hashtable,目的是通過給每個對象分配一個的索引來提高查詢的效率。那么Java也不會肆意扭曲改變這個概念,所以hashCode的作用就是為支持數據結構中的哈希表結構而存在的,換句話說,也就是只有用到集合框架的Hashtable、HashMap、HashSet的時候,才需要重載hashCode()方法,這樣才能使得我們能人為的去控制在哈希結構中索引是否相等。筆者舉一個例子:曾經為了寫一個求解類程序,需要隨機列出1,2,3,4組成的不同排列組合,所以筆者寫了一個數組類用int[]來存組合結果,然后把隨機產生的組合加入一個HashSet中,就是想利用HashSet不包括重復元素的特點??墒荋ashSet怎么判斷是不是重復的元素呢?當然是通過hashCode()返回的結果是否相等來判斷啦,可做一下這個實驗:
int[]A={1,2,3,4};
int[]B={1,2,3,4};
System.out.println(A.hashCode());
System.out.println(B.hashCode());
這明明是同一種組合,卻是不同的hashCode,加入Set的時候會被當成不同的對象。這個時候我們就需要自己來重寫hashCode()方法了,如何寫呢?其實也是基于原始的hashCode(),畢竟那是操作系統(tǒng)的實現,找到相通對象的標識,實現方式很多,筆者的實現方式是:首先重寫了toString()方法:return A[0]“+”A[1]“+”A[2]“+”A[3];//顯示上比較直觀然后利用toString()來計算hashCode():return this.toString()。hashCode();這樣上述A和B返回的就都是“1234”,在測試toString()。hashCode(),由于String在內存中的副本是一樣的,“1234”。hashCode()返回的一定是相同的結果。
說到這,相信大家能理解得比我更好,今后千萬不要再誤解hashCode()方法的作用。

