第二章:創(chuàng)建和銷(xiāo)毀對(duì)象
第7條:避免使用終結(jié)方法
final、finally、finalize的區(qū)別:
final:修飾符,關(guān)鍵字,可以修飾成員、方法和類(lèi),如果類(lèi)被聲明為final,意味著它不能再派生出新的子類(lèi),不能作為父類(lèi)被繼承。將變量或者方法聲明為final,可以保證他們?cè)谑褂弥胁槐桓淖儭?finally:一般是用于異常處理中,提供finally塊來(lái)執(zhí)行任何的清楚操作,try{} catch(){} finally{}。
finalize:用于垃圾回收,在java中,允許使用finalize()方法在垃圾收集器將對(duì)象從內(nèi)存中清理出去之前做必要的清理工作。
第三章對(duì)所有對(duì)象都通用的方法
第8條:覆蓋equals時(shí)請(qǐng)遵守通用約定
- 使用==操作符檢查“參數(shù)是否為這個(gè)對(duì)象的引用”。
- 使用instanceof操作符檢查“參數(shù)是否為正確的類(lèi)型”。
- 把參數(shù)轉(zhuǎn)換成正確的類(lèi)型。
- 對(duì)于該類(lèi)中的每個(gè)“關(guān)鍵”域,檢查參數(shù)中的域是否與該對(duì)象中對(duì)應(yīng)域相匹配。
- 當(dāng)覆蓋玩equals方法之后,應(yīng)該問(wèn)自己三個(gè)問(wèn)題:它是否對(duì)稱(chēng)的、傳遞的、一致的?
warning:
- 覆蓋equals時(shí)總要覆蓋hashCode;
- 不要企圖讓equals方法過(guò)于智能;
- 不要將equals聲明中的Object對(duì)象替換為其他的類(lèi)型;
public boolean equals(Myclass myclass){
.....
}
第9條:覆蓋equals時(shí)總要覆蓋hashCode
每個(gè)覆蓋了equals方法的類(lèi)中,也必須改服hashCode方法;
相等的對(duì)象必須具有相等的散列碼;
為不相等的對(duì)象產(chǎn)生不相等的散列碼;
不要試圖從散列碼計(jì)算中排除一個(gè)對(duì)象的關(guān)鍵部分來(lái)提高性能;
第10條:始終要覆蓋toString()
java.lang.Object提供了一個(gè)toString()方法,其結(jié)果為類(lèi)名+@+hashCode十六位無(wú)符號(hào)表示方法。覆蓋toString()方法,獲取簡(jiǎn)潔的類(lèi)toString()結(jié)果,便于程序中類(lèi)輸入結(jié)果的閱讀。
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
第11條:謹(jǐn)慎地覆蓋clone
如果你覆蓋了非final類(lèi)中的clone方法,則應(yīng)該返回一個(gè)通過(guò)調(diào)用super.clone而得到的對(duì)象;
clone方法就是另一個(gè)構(gòu)造器,你必須確保不會(huì)傷害到原始的對(duì)象,并確保正確地創(chuàng)建克隆對(duì)象中的約束條件;
第12條:考慮實(shí)現(xiàn)Complarable接口
Object中并沒(méi)有聲明compareTo()方法,compartTo()是Comparable接口的唯一方法,繼承此接口的類(lèi),可以實(shí)現(xiàn)類(lèi)內(nèi)部排序;
public interface Comparable{
public int compareTo(T o);
}
其返回結(jié)果為int型,當(dāng)對(duì)象小于、等于、大于指定對(duì)象T時(shí),返回結(jié)果分別為負(fù)整數(shù)、零和正整數(shù);
第4章:類(lèi)與接口
第13條:使類(lèi)和成員的可訪問(wèn)性最小化
盡可能地使每個(gè)類(lèi)或者成員不被外界訪問(wèn);
可訪問(wèn)性:
- 私有的private;
- 包級(jí)私有的package-private,聲明該成員包內(nèi)部的任何類(lèi)都可以訪問(wèn)這個(gè)成員,不對(duì)成員做任何訪問(wèn)級(jí)別限制,則默認(rèn)為包級(jí)私有;
- 受保護(hù)的protected,類(lèi)及其子類(lèi)可訪問(wèn)protected級(jí)別成員;
- 公開(kāi)的public,在任何地方都可以訪問(wèn)該成員;
第14條:在公有類(lèi)中使用訪問(wèn)方法而非公有域
公有類(lèi)永遠(yuǎn)不要暴露可變的域。雖然這還是有問(wèn)題,但是讓公有類(lèi)暴露不可變的域其危害比較小。
第15條:使可變性最小化
為了使類(lèi)成為不可變,要遵循下面五條規(guī)則:
- 不要提供任何會(huì)修改對(duì)象狀態(tài)的方法;
- 保證類(lèi)不會(huì)被擴(kuò)展;
- 使所有的域都是final的;
- 使所有的域都成為私有的;
- 確保對(duì)于任何可變組件的互斥訪問(wèn);
第16條:復(fù)合優(yōu)于繼承
只有子類(lèi)真正是超類(lèi)的一部分時(shí),才可以使用繼承,即當(dāng)子類(lèi)只有包含超類(lèi)的屬性時(shí)才能使用繼承;
繼承的功能非常強(qiáng)大,但是由于繼承違背了封裝原則,因此也存在諸多問(wèn)題。可以用復(fù)合和轉(zhuǎn)發(fā)機(jī)制來(lái)代替繼承,尤其是當(dāng)存在適當(dāng)?shù)慕涌趯?shí)現(xiàn)包裝類(lèi)時(shí),包裝類(lèi)比子類(lèi)更加健壯,功能也更強(qiáng)大;
第17條:要么為繼承而設(shè)計(jì),并提交文檔說(shuō)明,要么就禁止繼承
第18條:接口優(yōu)于抽象類(lèi)
第19條:接口只用于定義類(lèi)型
接口只應(yīng)用于定義類(lèi)型,而不應(yīng)該被用來(lái)到處常量;
第20條:類(lèi)層次優(yōu)于標(biāo)簽類(lèi)
標(biāo)簽類(lèi)過(guò)于冗長(zhǎng),容易出錯(cuò),并且效率低下;
第21條:用函數(shù)對(duì)象表示策略
第22條:優(yōu)先考慮使用靜態(tài)成員類(lèi)
嵌套類(lèi):是指被定義在另一個(gè)類(lèi)的內(nèi)部的類(lèi);
嵌套類(lèi)分類(lèi):靜態(tài)成員類(lèi)、非靜態(tài)成員類(lèi)、匿名類(lèi)、局部類(lèi);
第6章 枚舉和接口
第30條:用enum代替int常量
枚舉類(lèi)型:是指由一組固定的常量組合成合法值得類(lèi)型,例如一年的春夏秋冬四個(gè)季節(jié);
為了將數(shù)據(jù)與枚舉常量關(guān)聯(lián)起來(lái),得聲明實(shí)例域,并編寫(xiě)一個(gè)帶有數(shù)據(jù)并將數(shù)據(jù)保存在域中的構(gòu)造器。
第31條:用實(shí)例域代替序數(shù)
永遠(yuǎn)不要根據(jù)枚舉的序數(shù)導(dǎo)出與它關(guān)聯(lián)的值,而是將它保存在一個(gè)實(shí)例域中。
第32條:用EnumSet代替位域
用OR位運(yùn)算將幾個(gè)常量合并到一個(gè)集合中,稱(chēng)作位域;
EnumSet類(lèi)可以有效地從單個(gè)枚舉類(lèi)型中提取多個(gè)枚舉值;
eg:
public enum Style{
BOLD,
ITALIC,
UNDERLINE
}
Set<Style> styleSet = EnumSet.of(Style.BOLD,Style.ITALIC);
由于枚舉類(lèi)型要用在集合set中,所以沒(méi)有理由用位域表示它。
第33條:用EnumMap代替序數(shù)索引
EnumMap繼承AbstractMap實(shí)現(xiàn)Map接口,其實(shí)現(xiàn)Map所有操作的同時(shí),具有獲取鍵列表和值列表功能;
getKeyUniverse()返回鍵列表,values()返回值列表;
第34條:用接口模擬可伸縮的枚舉
雖然無(wú)法編寫(xiě)可擴(kuò)展的枚舉類(lèi)型,卻可以通過(guò)編寫(xiě)接口以及實(shí)現(xiàn)該接口的基礎(chǔ)枚舉類(lèi)型,對(duì)它進(jìn)行模擬;
第35條:注解優(yōu)先于命名模式
一般使用命名模式,表明有些程序需要通過(guò)某種工具或者框架進(jìn)行特殊處理;
java 元注解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
有了注解,就不需要再使用命名模式了;
第36條:堅(jiān)持使用override注解
使用@Override注解,表示該方法覆蓋超類(lèi)中的方法;此注解保留源碼級(jí)別,當(dāng)java文件被編譯后,@Override會(huì)被去除;使用此注解便于程序員對(duì)程序的理解,此外編譯器會(huì)根據(jù)此注解對(duì)無(wú)意識(shí)的覆蓋給予提示;
第37條:用標(biāo)記接口定義類(lèi)型
標(biāo)記接口:是沒(méi)有包含方法聲明的接口,例如:Serializable就是一個(gè)標(biāo)記接口,通過(guò)實(shí)現(xiàn)此接口,表明類(lèi)可以被序列化。
第7章 方法
第38條:檢查參數(shù)的有效性
對(duì)參數(shù)的任何限制都是件好事。再設(shè)計(jì)方法時(shí),應(yīng)該使它們盡可能的通用,并符合實(shí)際需要。
每當(dāng)編寫(xiě)方式或者構(gòu)造器的時(shí)候,應(yīng)該考慮它的參數(shù)有哪些限制。應(yīng)該把這些限制寫(xiě)在文檔中,并且在這個(gè)方法體的開(kāi)頭處,通過(guò)顯式的檢查來(lái)實(shí)施這些限制。
第39條:必要時(shí)進(jìn)行保護(hù)性拷貝
- 類(lèi)的客戶(hù)端會(huì)盡其所能來(lái)破壞這個(gè)類(lèi)的約束條件,因此你必須保護(hù)性地設(shè)計(jì)程序。
- 保護(hù)性拷貝是在檢查參數(shù)的有效性之前進(jìn)行的,并且有效性檢查是針對(duì)拷貝之后的對(duì)象,而不是針對(duì)原始對(duì)象。
- 對(duì)于參數(shù)類(lèi)型可以被不可信任方子類(lèi)話的參數(shù),請(qǐng)不要使用clone方法進(jìn)行保護(hù)性拷貝。
保護(hù)性拷貝示例
public Date start(){
return new Date(start.getTime());
}
第40條:謹(jǐn)慎設(shè)計(jì)方法簽名
- 謹(jǐn)慎的選擇方法名稱(chēng),應(yīng)該始終遵循標(biāo)準(zhǔn)的命名習(xí)慣;
- 不要過(guò)于追求提供便利的方法;
- 避免過(guò)長(zhǎng)的參數(shù)列表,可以通過(guò)輔助類(lèi)縮短參數(shù)列表;
第41條:慎用重載
永遠(yuǎn)不要導(dǎo)出兩個(gè)具有相同參數(shù)目的的重載方法
第42條:慎用可變參數(shù)
在定義參數(shù)數(shù)目不定的方法時(shí),可變參數(shù)方法時(shí)不種很方便的方法,但是它們不應(yīng)該過(guò)度濫用。如果使用不當(dāng),會(huì)產(chǎn)生混亂的結(jié)果。
第43條:返回零長(zhǎng)度或者集合,而不是null
返回類(lèi)型為數(shù)組或集合的方法沒(méi)理由返回null,應(yīng)該返回零長(zhǎng)度的數(shù)組或集合;
第44條:為所有導(dǎo)出的API元素編寫(xiě)文檔注釋
第八章 通過(guò)程序設(shè)計(jì)
第45條:將局部變量作用域最小化
將局部變量最小化,可以增強(qiáng)代碼的可讀性和可維護(hù)性,并降低錯(cuò)的可能性。
- 要使局部變量的作用域最小化,最有力的方法就是在第一次使用它的時(shí)候聲明;
第46條:for-each循環(huán)優(yōu)先于傳統(tǒng)的for循環(huán)
java1.5發(fā)行版本中引入for-each循環(huán),通過(guò)完全隱藏迭代器或者索引變量,便面了混亂和出錯(cuò)的可能。eg:
for(Element e : elements){
doSomeThing(e);
}
有三種情況無(wú)法使用for-each循環(huán):
- 過(guò)濾--如果需要遍歷集合或者數(shù)組,并刪除指定的元素;
- 轉(zhuǎn)換--如果需要遍歷列表或者數(shù)組,并取代它不分或者全部的元素值;
- 平行迭代--如果需要并行地遍歷多個(gè)集合,就需要顯式地控制迭代器或者索引變量,以便所有迭代器或者索引量都可以得到同步前移;
第47條:了解和使用類(lèi)庫(kù)
java.io java.lang java.util java.util.concurrent類(lèi)庫(kù)是每個(gè)程序員都應(yīng)該學(xué)習(xí)的;
多了解類(lèi)庫(kù),多閱讀類(lèi)庫(kù)實(shí)現(xiàn)原理及實(shí)現(xiàn)方式,類(lèi)庫(kù)的代碼比你自己編寫(xiě)的代碼更好一些,并隨著時(shí)間推移而不斷改進(jìn)。
第48條:如果需要精確的答案,避免私用floate和double
使用BigDecimal代替floate和double
第49條:基本類(lèi)型有限裝箱基本類(lèi)型
基本類(lèi)型與基本裝箱類(lèi)型的區(qū)別:
- 基本類(lèi)型只有值,裝箱基本類(lèi)型則具有它們的值不同的同一性;
- 基本類(lèi)型只有功能完備的值,而每個(gè)裝箱基本類(lèi)型除了它對(duì)基本類(lèi)型的所有功能值之外,還有個(gè)非功能值:null
- 基本類(lèi)型比裝箱基本類(lèi)型更節(jié)約時(shí)間和空間
第50條:如果其他類(lèi)型更合適,避免使用字符串
字符串不適合代替其他值類(lèi)型
字符串不適合代替枚舉類(lèi)型
字符串不適合代替能力表
如果可以使用更加合適的數(shù)據(jù)類(lèi)型,或者可以編寫(xiě)更加適當(dāng)?shù)臄?shù)據(jù)類(lèi)型,就應(yīng)該避免使用字符串
第51條:當(dāng)心字符串連接的性能
為了獲取能夠接受的性能,請(qǐng)使用StringBuilder代替String
第52條:通過(guò)接口引用對(duì)象
如果有合適的接口類(lèi)型存在,那么對(duì)于參數(shù)、返回值、變量和域來(lái)說(shuō),就都應(yīng)該使用接口類(lèi)型進(jìn)行聲明;
第53條:接口優(yōu)先于反射機(jī)制
核心反射機(jī)制:提供了“通過(guò)程序來(lái)訪問(wèn)關(guān)于已裝載的類(lèi)的信息”的能力;
第54條:謹(jǐn)慎地使用本地方法
本地方法是指用本地程序設(shè)計(jì)語(yǔ)言(c或者c++)來(lái)編寫(xiě)的特殊方法;
本地方法時(shí)不安全的,使用本地方法的應(yīng)用程序不再能免受內(nèi)存毀壞錯(cuò)誤的影響。因?yàn)楸镜卣Z(yǔ)言是平臺(tái)相關(guān)的,使用本地方法的語(yǔ)言不再是可移植的。
第55條:謹(jǐn)慎地優(yōu)化
要努力編寫(xiě)好的程序而不是快的程序
每次試圖優(yōu)化之前和之后,要對(duì)性能進(jìn)行測(cè)量
第56條:要遵循普遍的命名規(guī)范
跟著項(xiàng)目走,寫(xiě)代碼時(shí)重視命名規(guī)范
....未完待續(xù)