第二章:創(chuàng)建和銷毀對象
第7條:避免使用終結方法
final兔跌、finally、finalize的區(qū)別:
final:修飾符帝嗡,關鍵字晶通,可以修飾成員、方法和類哟玷,如果類被聲明為final狮辽,意味著它不能再派生出新的子類,不能作為父類被繼承巢寡。將變量或者方法聲明為final喉脖,可以保證他們在使用中不被改變。
finally:一般是用于異常處理中抑月,提供finally塊來執(zhí)行任何的清楚操作树叽,try{} catch(){} finally{}。
finalize:用于垃圾回收谦絮,在java中题诵,允許使用finalize()方法在垃圾收集器將對象從內存中清理出去之前做必要的清理工作。
第三章對所有對象都通用的方法
第8條:覆蓋equals時請遵守通用約定
- 使用==操作符檢查“參數(shù)是否為這個對象的引用”层皱。
- 使用instanceof操作符檢查“參數(shù)是否為正確的類型”性锭。
- 把參數(shù)轉換成正確的類型。
- 對于該類中的每個“關鍵”域奶甘,檢查參數(shù)中的域是否與該對象中對應域相匹配篷店。
- 當覆蓋玩equals方法之后祭椰,應該問自己三個問題:它是否對稱的臭家、傳遞的疲陕、一致的?
warning:
- 覆蓋equals時總要覆蓋hashCode钉赁;
- 不要企圖讓equals方法過于智能蹄殃;
- 不要將equals聲明中的Object對象替換為其他的類型;
public boolean equals(Myclass myclass){
.....
}
第9條:覆蓋equals時總要覆蓋hashCode
每個覆蓋了equals方法的類中你踩,也必須改服hashCode方法诅岩;
相等的對象必須具有相等的散列碼;
為不相等的對象產(chǎn)生不相等的散列碼带膜;
不要試圖從散列碼計算中排除一個對象的關鍵部分來提高性能吩谦;
第10條:始終要覆蓋toString()
java.lang.Object提供了一個toString()方法,其結果為類名+@+hashCode十六位無符號表示方法膝藕。覆蓋toString()方法式廷,獲取簡潔的類toString()結果,便于程序中類輸入結果的閱讀芭挽。
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
第11條:謹慎地覆蓋clone
如果你覆蓋了非final類中的clone方法滑废,則應該返回一個通過調用super.clone而得到的對象;
clone方法就是另一個構造器袜爪,你必須確保不會傷害到原始的對象蠕趁,并確保正確地創(chuàng)建克隆對象中的約束條件;
第12條:考慮實現(xiàn)Complarable接口
Object中并沒有聲明compareTo()方法辛馆,compartTo()是Comparable接口的唯一方法俺陋,繼承此接口的類,可以實現(xiàn)類內部排序昙篙;
public interface Comparable{
public int compareTo(T o);
}
其返回結果為int型倔韭,當對象小于、等于瓢对、大于指定對象T時寿酌,返回結果分別為負整數(shù)、零和正整數(shù)硕蛹;
第4章:類與接口
第13條:使類和成員的可訪問性最小化
盡可能地使每個類或者成員不被外界訪問醇疼;
可訪問性:
- 私有的private;
- 包級私有的package-private法焰,聲明該成員包內部的任何類都可以訪問這個成員秧荆,不對成員做任何訪問級別限制,則默認為包級私有埃仪;
- 受保護的protected乙濒,類及其子類可訪問protected級別成員;
- 公開的public,在任何地方都可以訪問該成員颁股;
第14條:在公有類中使用訪問方法而非公有域
公有類永遠不要暴露可變的域么库。雖然這還是有問題,但是讓公有類暴露不可變的域其危害比較小甘有。
第15條:使可變性最小化
為了使類成為不可變诉儒,要遵循下面五條規(guī)則:
- 不要提供任何會修改對象狀態(tài)的方法;
- 保證類不會被擴展亏掀;
- 使所有的域都是final的忱反;
- 使所有的域都成為私有的;
- 確保對于任何可變組件的互斥訪問滤愕;
第16條:復合優(yōu)于繼承
只有子類真正是超類的一部分時温算,才可以使用繼承,即當子類只有包含超類的屬性時才能使用繼承间影;
繼承的功能非常強大米者,但是由于繼承違背了封裝原則,因此也存在諸多問題宇智÷悖可以用復合和轉發(fā)機制來代替繼承,尤其是當存在適當?shù)慕涌趯崿F(xiàn)包裝類時随橘,包裝類比子類更加健壯喂分,功能也更強大;
第17條:要么為繼承而設計机蔗,并提交文檔說明蒲祈,要么就禁止繼承
第18條:接口優(yōu)于抽象類
第19條:接口只用于定義類型
接口只應用于定義類型,而不應該被用來到處常量萝嘁;
第20條:類層次優(yōu)于標簽類
標簽類過于冗長梆掸,容易出錯,并且效率低下牙言;
第21條:用函數(shù)對象表示策略
第22條:優(yōu)先考慮使用靜態(tài)成員類
嵌套類:是指被定義在另一個類的內部的類酸钦;
嵌套類分類:靜態(tài)成員類、非靜態(tài)成員類咱枉、匿名類卑硫、局部類;
第6章 枚舉和接口
第30條:用enum代替int常量
枚舉類型:是指由一組固定的常量組合成合法值得類型蚕断,例如一年的春夏秋冬四個季節(jié)欢伏;
為了將數(shù)據(jù)與枚舉常量關聯(lián)起來,得聲明實例域亿乳,并編寫一個帶有數(shù)據(jù)并將數(shù)據(jù)保存在域中的構造器硝拧。
第31條:用實例域代替序數(shù)
永遠不要根據(jù)枚舉的序數(shù)導出與它關聯(lián)的值,而是將它保存在一個實例域中。
第32條:用EnumSet代替位域
用OR位運算將幾個常量合并到一個集合中障陶,稱作位域滋恬;
EnumSet類可以有效地從單個枚舉類型中提取多個枚舉值;
eg:
public enum Style{
BOLD,
ITALIC,
UNDERLINE
}
Set<Style> styleSet = EnumSet.of(Style.BOLD,Style.ITALIC);
由于枚舉類型要用在集合set中咸这,所以沒有理由用位域表示它夷恍。
第33條:用EnumMap代替序數(shù)索引
EnumMap繼承AbstractMap實現(xiàn)Map接口魔眨,其實現(xiàn)Map所有操作的同時媳维,具有獲取鍵列表和值列表功能;
getKeyUniverse()返回鍵列表遏暴,values()返回值列表侄刽;
第34條:用接口模擬可伸縮的枚舉
雖然無法編寫可擴展的枚舉類型,卻可以通過編寫接口以及實現(xiàn)該接口的基礎枚舉類型朋凉,對它進行模擬州丹;
第35條:注解優(yōu)先于命名模式
一般使用命名模式,表明有些程序需要通過某種工具或者框架進行特殊處理杂彭;
java 元注解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
有了注解墓毒,就不需要再使用命名模式了;
第36條:堅持使用override注解
使用@Override注解亲怠,表示該方法覆蓋超類中的方法所计;此注解保留源碼級別,當java文件被編譯后团秽,@Override會被去除主胧;使用此注解便于程序員對程序的理解,此外編譯器會根據(jù)此注解對無意識的覆蓋給予提示习勤;
第37條:用標記接口定義類型
標記接口:是沒有包含方法聲明的接口踪栋,例如:Serializable就是一個標記接口,通過實現(xiàn)此接口图毕,表明類可以被序列化夷都。
第7章 方法
第38條:檢查參數(shù)的有效性
對參數(shù)的任何限制都是件好事。再設計方法時予颤,應該使它們盡可能的通用损肛,并符合實際需要。
每當編寫方式或者構造器的時候荣瑟,應該考慮它的參數(shù)有哪些限制治拿。應該把這些限制寫在文檔中,并且在這個方法體的開頭處笆焰,通過顯式的檢查來實施這些限制劫谅。
第39條:必要時進行保護性拷貝
- 類的客戶端會盡其所能來破壞這個類的約束條件,因此你必須保護性地設計程序。
- 保護性拷貝是在檢查參數(shù)的有效性之前進行的捏检,并且有效性檢查是針對拷貝之后的對象荞驴,而不是針對原始對象。
- 對于參數(shù)類型可以被不可信任方子類話的參數(shù)贯城,請不要使用clone方法進行保護性拷貝熊楼。
保護性拷貝示例
public Date start(){
return new Date(start.getTime());
}
第40條:謹慎設計方法簽名
- 謹慎的選擇方法名稱,應該始終遵循標準的命名習慣能犯;
- 不要過于追求提供便利的方法鲫骗;
- 避免過長的參數(shù)列表,可以通過輔助類縮短參數(shù)列表踩晶;
第41條:慎用重載
永遠不要導出兩個具有相同參數(shù)目的的重載方法
第42條:慎用可變參數(shù)
在定義參數(shù)數(shù)目不定的方法時执泰,可變參數(shù)方法時不種很方便的方法,但是它們不應該過度濫用渡蜻。如果使用不當术吝,會產(chǎn)生混亂的結果。
第43條:返回零長度或者集合茸苇,而不是null
返回類型為數(shù)組或集合的方法沒理由返回null排苍,應該返回零長度的數(shù)組或集合;
第44條:為所有導出的API元素編寫文檔注釋
第八章 通過程序設計
第45條:將局部變量作用域最小化
將局部變量最小化学密,可以增強代碼的可讀性和可維護性淘衙,并降低錯的可能性。
- 要使局部變量的作用域最小化则果,最有力的方法就是在第一次使用它的時候聲明幔翰;
第46條:for-each循環(huán)優(yōu)先于傳統(tǒng)的for循環(huán)
java1.5發(fā)行版本中引入for-each循環(huán),通過完全隱藏迭代器或者索引變量西壮,便面了混亂和出錯的可能遗增。eg:
for(Element e : elements){
doSomeThing(e);
}
有三種情況無法使用for-each循環(huán):
- 過濾--如果需要遍歷集合或者數(shù)組,并刪除指定的元素款青;
- 轉換--如果需要遍歷列表或者數(shù)組做修,并取代它不分或者全部的元素值;
- 平行迭代--如果需要并行地遍歷多個集合抡草,就需要顯式地控制迭代器或者索引變量饰及,以便所有迭代器或者索引量都可以得到同步前移;
第47條:了解和使用類庫
java.io java.lang java.util java.util.concurrent類庫是每個程序員都應該學習的康震;
多了解類庫燎含,多閱讀類庫實現(xiàn)原理及實現(xiàn)方式,類庫的代碼比你自己編寫的代碼更好一些腿短,并隨著時間推移而不斷改進屏箍。
第48條:如果需要精確的答案绘梦,避免私用floate和double
使用BigDecimal代替floate和double
第49條:基本類型有限裝箱基本類型
基本類型與基本裝箱類型的區(qū)別:
- 基本類型只有值,裝箱基本類型則具有它們的值不同的同一性赴魁;
- 基本類型只有功能完備的值卸奉,而每個裝箱基本類型除了它對基本類型的所有功能值之外,還有個非功能值:null
- 基本類型比裝箱基本類型更節(jié)約時間和空間
第50條:如果其他類型更合適颖御,避免使用字符串
字符串不適合代替其他值類型
字符串不適合代替枚舉類型
字符串不適合代替能力表
如果可以使用更加合適的數(shù)據(jù)類型榄棵,或者可以編寫更加適當?shù)臄?shù)據(jù)類型,就應該避免使用字符串
第51條:當心字符串連接的性能
為了獲取能夠接受的性能潘拱,請使用StringBuilder代替String
第52條:通過接口引用對象
如果有合適的接口類型存在疹鳄,那么對于參數(shù)、返回值泽铛、變量和域來說尚辑,就都應該使用接口類型進行聲明辑鲤;
第53條:接口優(yōu)先于反射機制
核心反射機制:提供了“通過程序來訪問關于已裝載的類的信息”的能力盔腔;
第54條:謹慎地使用本地方法
本地方法是指用本地程序設計語言(c或者c++)來編寫的特殊方法;
本地方法時不安全的月褥,使用本地方法的應用程序不再能免受內存毀壞錯誤的影響弛随。因為本地語言是平臺相關的,使用本地方法的語言不再是可移植的宁赤。
第55條:謹慎地優(yōu)化
要努力編寫好的程序而不是快的程序
每次試圖優(yōu)化之前和之后舀透,要對性能進行測量
第56條:要遵循普遍的命名規(guī)范
跟著項目走,寫代碼時重視命名規(guī)范
....未完待續(xù)