從靜態(tài)代碼分析工具的檢測(cè)規(guī)則學(xué)習(xí)代碼優(yōu)化技巧
講起靜態(tài)代碼分析工具,估計(jì)大家耳熟能詳?shù)亩寄苤v出幾個(gè)來,像PMD, Checkstyle, Findbug等。沒錯(cuò)這些都是我們?nèi)粘>幋a代碼時(shí)用于提升我們代碼質(zhì)量的好工具,本文將從PMD工具實(shí)現(xiàn)的規(guī)則出發(fā),通過這些規(guī)則的定義來學(xué)習(xí)一下代碼優(yōu)化的技巧,希望通過這些技巧的介紹可以幫助大家在編碼過程中提升大家的代碼編寫質(zhì)量。同時(shí)也算給大家介紹一個(gè)比較不錯(cuò)的途徑去學(xué)習(xí)改進(jìn)代碼編寫質(zhì)量的方法。
下面都是從PMD規(guī)則中總結(jié)的一部分代碼優(yōu)化建議:
1.局部變量只被賦值一次可以聲明為final
說明: 使用final標(biāo)識(shí)后,Java在編譯的時(shí)候會(huì)自動(dòng)把變化替換成常量,這樣程序的運(yùn)行效率就會(huì)提升
2.如果傳入長(zhǎng)度為1的字面意義參數(shù),這調(diào)用String.startsWith 可以使用 String.charAt(0) 方法節(jié)省運(yùn)行時(shí)間
說明:關(guān)于這點(diǎn)比較好理解,String對(duì)象本身就是char數(shù)組,String.startsWith方法在內(nèi)部處理比較復(fù)雜,又有循環(huán)比較操作,所以效率遠(yuǎn)不及charAt操作。
“Abc”.startsWith(“A”) //bad
“Abc”.charAt(0) == ‘A’ //good
3.字符串拼接,使用StringBuffer,而不是直接使用”+”操作符進(jìn)行拼接
說明: 關(guān)于這一點(diǎn),大家都有認(rèn)識(shí)。因?yàn)橹苯拥腟tring對(duì)象拼接,會(huì)產(chǎn)生新的String的對(duì)象進(jìn)行存儲(chǔ)。StringBuffer則會(huì)申請(qǐng)一個(gè)較大的內(nèi)存空間(char數(shù)組), 針對(duì)拼接,如果沒有超過char數(shù)組大小就直接追加到該數(shù)組尾部. 注意StringBuffer默認(rèn)大小是16個(gè)字符,所以建議大家使用時(shí)指定創(chuàng)建的數(shù)組大小。
4.String 的indexOf方法,如果參數(shù)單個(gè)字母,則使用char
Abc”.indexOf (“A”) //bad
Abc”.indexOf(‘A’) //good
說明:String indexOf 方法,針對(duì)String和char的查找是使用了兩個(gè)方法,有興趣的同學(xué)可以看一下String的原代碼,查找String的方法要比查找char方法復(fù)雜,相對(duì)耗時(shí)
5.建議不要使用無參的StringBuffer構(gòu)造函數(shù)(該初始長(zhǎng)度為16個(gè)字符)
說明: 大家可能對(duì)StringBuffer有一些誤解,認(rèn)為StringBuffer初始的空間比較大,但實(shí)際上其默認(rèn)創(chuàng)建的大小只是16個(gè)字符的數(shù)組,一旦超過后,需要新申請(qǐng)的數(shù)組空間,這個(gè)就會(huì)有額外的開銷。
6.非線程安全的單例實(shí)現(xiàn) NonThreadSafeSingleton
下面代碼是單例實(shí)現(xiàn)中比較常見的一種

但這段代碼引入的一個(gè)問題,就是在多線程方式下運(yùn)行,有可能會(huì)出復(fù)重新創(chuàng)建對(duì)象的問題。解決辦法在getFoo方法上加上 synchronized關(guān)鍵字
7.同時(shí)需要覆寫 hashCode和equals方法
說明:這個(gè)也是大家偶爾會(huì)忽視的一個(gè)問題。hashCode和equlas方法最主要的用途是在基本Hash算法的集合類中,如HashMap,等。
在HashMap實(shí)現(xiàn)中,其對(duì)一個(gè)對(duì)方是否相等的判斷邏輯如下:

也就是說在HashMap中如果兩個(gè)對(duì)象相等必須是hashCode相等并且equals方法也返回相等。
那如果在一個(gè)對(duì)象中,只復(fù)寫了equals,而未復(fù)寫hashCode方法,就會(huì)造成”重復(fù)”的對(duì)象在HashSet中也會(huì)發(fā)生。
下面是一個(gè)有問題的示例代碼:

8.BigDecimal對(duì)象初始化時(shí),針對(duì)浮點(diǎn)數(shù)據(jù)值使用String參數(shù)(針對(duì)精度問題)
說明:例如 new BigDecimal(0.1) 值真正的值可能是 .1000000000000000055511151231257827021181583404541015625
Good Luck!
Yours Matthew!
【編輯推薦】