自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

高手支招 Java經(jīng)驗(yàn)分享(三)

開(kāi)發(fā) 后端
本篇文章是作者Ant_Yan在CSDN論壇上發(fā)布的自己對(duì)Java學(xué)習(xí)的一些經(jīng)驗(yàn)分享。這是他經(jīng)驗(yàn)分享的第三部分。

  前兩次分別講述了Java關(guān)于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。這次仍然不準(zhǔn)備開(kāi)始過(guò)渡到j(luò)2ee中,因?yàn)橛X(jué)得還有一些瑣碎的j2se的問(wèn)題沒(méi)有總結(jié)完畢。

  1. 關(guān)于Object類(lèi)理解

  大家都知道Object是所有Java類(lèi)的基類(lèi), 意味著所有的Java類(lèi)都會(huì)繼承了Object的11個(gè)方法。建議大家去看看Object的 11個(gè)成員函數(shù)的源代碼,就會(huì)知道默認(rèn)的實(shí)現(xiàn)方式。比如equals方法,默認(rèn)實(shí)現(xiàn)就是用"=="來(lái)比較,即直接比較內(nèi)存地址,返回true 或者 false。而toString()方法,返回的串組成方式是:

  1. "getClass().getName() + "@" + Integer.toHexString(hashCode())" 

  其實(shí)不用我過(guò)多的解釋?zhuān)蠹叶寄芸炊@個(gè)串的組成。接下來(lái)再看看hashCode():

  1. public native int hashCode(); 

  由于是native方法,跟OS的處理方式相關(guān),源代碼里僅僅有一個(gè)聲明罷了。我們有興趣的話完全可以去深究它的hashCode到底是由OS怎么樣產(chǎn)生的呢?但筆者建議最重要的還是先記住使用它的幾條原則吧!首先如果equals()方法相同的對(duì)象具有相通的hashCode,但equals ()對(duì)象不相通的時(shí)候并不保證hashCode()方法返回不同的整數(shù)。而且下一次運(yùn)行同一個(gè)程序,同一個(gè)對(duì)象未必還是當(dāng)初的那個(gè)hashCode() 哦。

  其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,說(shuō)明依賴(lài)于操作系統(tǒng)的實(shí)現(xiàn)。最后一個(gè)有趣的方法是finalize(),類(lèi)似C++的析構(gòu)函數(shù),簽名是protected,證明只有繼承擴(kuò)展了才能使用,方法體是空的,默示什么也不做。它的作用據(jù)筆者的了解僅僅是通知JVM此對(duì)象不再使用,隨時(shí)可以被銷(xiāo)毀,而實(shí)際的銷(xiāo)毀權(quán)還是在于虛擬機(jī)手上。那么它真的什么也不做麼?未必,實(shí)際上如果是線程對(duì)象它會(huì)導(dǎo)致在一定范圍內(nèi)該線程的優(yōu)先級(jí)別提高,導(dǎo)致更快的被銷(xiāo)毀來(lái)節(jié)約內(nèi)存提高性能。其實(shí)從常理來(lái)說(shuō),我們也可以大概這樣猜測(cè)出jvm做法的目的。

  2. 關(guān)于重載hashCode()與Collection框架的關(guān)系

  筆者曾經(jīng)聽(tīng)一位搞Java培訓(xùn)多年的前輩說(shuō)在他看來(lái)hashCode方法沒(méi)有任何意義,僅僅是為了配合證明具有同樣的hashCode會(huì)導(dǎo)致equals 方法相等而存在的。連有的前輩都犯這樣的錯(cuò)誤,其實(shí)說(shuō)明它還是滿容易被忽略的。那么hashCode()方法到底做什么用?

  學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)的課程大家都會(huì)知道有一種結(jié)構(gòu)叫hash table,目的是通過(guò)給每個(gè)對(duì)象分配一個(gè)唯一的索引來(lái)提高查詢(xún)的效率。那么Java也不會(huì)肆意扭曲改變這個(gè)概念,所以hashCode唯一的作用就是為支持?jǐn)?shù)據(jù)結(jié)構(gòu)中的哈希表結(jié)構(gòu)而存在的。換句話說(shuō),也就是只有用到集合框架的 Hashtable、HashMap、HashSet的時(shí)候,才需要重載hashCode()方法,這樣才能使得我們能人為的去控制在哈希結(jié)構(gòu)中索引是否相等。筆者舉一個(gè)例子:

  曾經(jīng)為了寫(xiě)一個(gè)求解類(lèi)程序,需要隨機(jī)列出1,2,3,4組成的不同排列組合,所以筆者寫(xiě)了一個(gè)數(shù)組類(lèi)用int[]來(lái)存組合結(jié)果,然后把隨機(jī)產(chǎn)生的組合加入一個(gè)HashSet中,就是想利用HashSet不包括重復(fù)元素的特點(diǎn)。可是HashSet怎么判斷是不是重復(fù)的元素呢?當(dāng)然是通過(guò) hashCode()返回的結(jié)果是否相等來(lái)判斷啦,可做一下這個(gè)實(shí)驗(yàn):

  1. int[] A = {1,2,3,4};  
  2. int[] B = {1,2,3,4};  
  3. System.out.println(A.hashCode());  
  4. System.out.println(B.hashCode()); 

  這明明是同一種組合,卻是不同的hashCode,加入Set的時(shí)候會(huì)被當(dāng)成不同的對(duì)象。這個(gè)時(shí)候我們就需要自己來(lái)重寫(xiě)hashCode()方法了,如何寫(xiě)呢?其實(shí)也是基于原始的hashCode(),畢竟那是操作系統(tǒng)的實(shí)現(xiàn), 找到相通對(duì)象唯一的標(biāo)識(shí),實(shí)現(xiàn)方式很多,筆者的實(shí)現(xiàn)方式是:

  首先重寫(xiě)了toString()方法:

  1. return A[0]“+” A[1]“+” A[2]“+” A[3]; //顯示上比較直觀 

  然后利用toString()來(lái)計(jì)算hashCode():

  1. return this.toString().hashCode(); 

  這樣上述A和B返回的就都是”1234”,在測(cè)試toString().hashCode(),由于String在內(nèi)存中的副本是一樣的,”1234”.hashCode()返回的一定是相同的結(jié)果。

  說(shuō)到這,相信大家能理解得比我更好,今后千萬(wàn)不要再誤解hashCode()方法的作用。

  3. 關(guān)于Class類(lèi)的成員函數(shù)與Java反射機(jī)制

  很早剛接觸Java就聽(tīng)很多老師說(shuō)過(guò)Java的動(dòng)態(tài)運(yùn)行時(shí)機(jī)制、反射機(jī)制等。確實(shí)它們都是Java的顯著特點(diǎn),運(yùn)行時(shí)加載筆者在第一篇介紹過(guò)了,現(xiàn)在想講講反射機(jī)制。在Java中,主要是通過(guò)java.lang包中的Class類(lèi)和Method類(lèi)來(lái)實(shí)現(xiàn)內(nèi)存反射機(jī)制的。

  熟悉C++的人一定知道下面這樣在C++中是做不到的: 運(yùn)行時(shí)以字符串參數(shù)傳遞一個(gè)類(lèi)名,就可以得到這個(gè)類(lèi)的所有信息,包括它所有的方法,和方法的詳細(xì)信息。還可以實(shí)例化一個(gè)對(duì)象,并通過(guò)查到的方法名來(lái)調(diào)用該對(duì)象的任何方法。這是因?yàn)镴ava的類(lèi)在內(nèi)存中除了C++中也有的靜態(tài)動(dòng)態(tài)數(shù)據(jù)區(qū)之外,還包括一份對(duì)類(lèi)自身的描述,也正是通過(guò)這描述中的信息,才能幫助我們才運(yùn)行時(shí)讀取里面的內(nèi)容,得到需要加載目標(biāo)類(lèi)的所有信息,從而實(shí)現(xiàn)反射機(jī)制。大家有沒(méi)有想過(guò)當(dāng)我們需要得到一個(gè)JavaBean的實(shí)例的時(shí)候,怎么知道它有哪些屬性呢?再明顯簡(jiǎn)單不過(guò)的例子就是自己寫(xiě)一個(gè)JavaBean的解析器:

  a. 通過(guò)Class.forName(“Bean的類(lèi)名”)得到Class對(duì)象,例如叫ABeanClass

  b. 通過(guò)ABeanClass的getMethods()方法,得到Method[]對(duì)象

  c. 按照規(guī)范所有g(shù)et方法名后的單詞就代表著該Bean的一個(gè)屬性

  d. 當(dāng)已經(jīng)知道一個(gè)方法名,可以調(diào)用newInstance()得到一個(gè)實(shí)例,然后通過(guò)invoke()方法將方法的名字和方法需要用的參數(shù)傳遞進(jìn)去,就可以動(dòng)態(tài)調(diào)用此方法。

  當(dāng)然還有更復(fù)雜的應(yīng)用,這里就不贅述,大家可以參考Class類(lèi)和Method類(lèi)的方法。

  4. 坦言Synchronize的本質(zhì)

  Synchronize大家都知道是同步、加鎖的意思,其實(shí)它的本質(zhì)遠(yuǎn)沒(méi)有大家想得那么復(fù)雜。聲明Synchronize的方法被調(diào)用的時(shí)候,鎖其實(shí)是加載對(duì)象上,當(dāng)然如果是靜態(tài)類(lèi)則是加在類(lèi)上的鎖,調(diào)用結(jié)束鎖被解除。它的實(shí)現(xiàn)原理很簡(jiǎn)單,僅僅是不讓第二把鎖再次被加在同一個(gè)對(duì)象或類(lèi)上,僅此而已。一個(gè)簡(jiǎn)單的例子足以說(shuō)明問(wèn)題:

  1. class A{  
  2.   synchronized void f(){}  
  3.   void g(){}  
  4.   } 

  當(dāng)A的一個(gè)對(duì)象a被第一個(gè)線程調(diào)用其f()方法的時(shí)候,第二個(gè)線程不能調(diào)用a的synchronized方法例如f(),因?yàn)槟鞘窃谠噲D在對(duì)象上加第二把鎖。但調(diào)用g()卻是可以的,因?yàn)椴](méi)有在同一對(duì)象上加兩把鎖的行為產(chǎn)生。

  這樣大家能理解了麼?明白它的原理能更好的幫助大家設(shè)計(jì)同步機(jī)制,不要濫用加鎖。

【編輯推薦】

  1. 新手入門(mén):學(xué)習(xí)Java的一點(diǎn)經(jīng)驗(yàn)心得
  2. 61條Java面向?qū)ο笤O(shè)計(jì)的經(jīng)驗(yàn)原則
  3. 經(jīng)驗(yàn)分享:我的JavaEE學(xué)習(xí)道路
  4. Java對(duì)象類(lèi)型轉(zhuǎn)換的四個(gè)經(jīng)驗(yàn)
責(zé)任編輯:韓亞珊 來(lái)源: CSDN
相關(guān)推薦

2011-03-31 13:52:22

Java

2011-03-31 16:26:28

Java

2011-03-31 15:36:02

Java

2011-03-31 14:07:27

Java

2011-03-31 16:44:43

Java

2011-03-31 16:49:40

Java

2011-03-31 14:49:35

2011-03-31 13:32:13

Java

2011-04-07 13:18:00

管理軟件項(xiàng)目項(xiàng)目

2009-10-29 16:57:05

Oracle傳輸表空間

2018-06-19 08:12:55

2011-07-13 17:42:32

CC++

2010-07-21 14:05:31

2014-05-28 10:55:11

Windows XP安全補(bǔ)丁

2010-08-18 14:19:01

無(wú)線路由器

2011-06-22 14:51:46

JAVA

2009-09-28 10:52:00

CCNA考試經(jīng)驗(yàn)CCNA

2009-02-06 10:39:22

NAS設(shè)備升級(jí)NAS

2011-07-15 17:35:19

JavaScript

2009-12-07 11:11:46

PHP顯示圖片
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)