第13條:使類和成員的可訪問(wèn)性最小化
這個(gè)被稱為信息隱藏或封裝与柑。它可以解耦流炕,使模塊可以獨(dú)立開(kāi)發(fā)、測(cè)試仅胞、優(yōu)化每辟、使用、理解和修改干旧∏郏可以讓開(kāi)發(fā)人員單獨(dú)調(diào)試自己的程序,提高開(kāi)發(fā)系統(tǒng)的速度椎眯,程序有問(wèn)題的時(shí)候挠将,可以準(zhǔn)確的定位在哪個(gè)模塊出現(xiàn)問(wèn)題,降低了構(gòu)建大型系統(tǒng)的風(fēng)險(xiǎn)编整。
訪問(wèn)控制機(jī)制決定了類舔稀、接口和成員的可訪問(wèn)性。
第一個(gè)規(guī)則:盡可能地使每個(gè)類或者成員不被外界訪問(wèn)掌测。類和接口只有兩種訪問(wèn)級(jí)別:包級(jí)私有(private)和公有的(public)内贮。
對(duì)于成員(域、方法汞斧、嵌套類和嵌套接口)有四種可能的訪問(wèn)級(jí)別夜郁,按訪問(wèn)性遞增順序羅列:
- 私有的(private),只有在聲明該成員的頂層類內(nèi)部才可以訪問(wèn)這個(gè)成員粘勒。
- 包級(jí)私有的(package-private)竞端,聲明改成員的包內(nèi)部的任何類都可以訪問(wèn)這個(gè)成員。從技術(shù)上講庙睡,它被稱為“缺适赂弧(default)訪問(wèn)級(jí)別”,如果沒(méi)有為成員指定訪問(wèn)修飾符乘陪,就采用這個(gè)訪問(wèn)級(jí)別统台。
- 受保護(hù)的(protected),聲明該成員的類的子類可以訪問(wèn)這個(gè)成員暂刘,并且饺谬,聲明該成員的包內(nèi)部的任何類也可以訪問(wèn)這個(gè)成員。
- 公有的(public),在任何地方都可以訪問(wèn)該成員募寨。
如果方法覆蓋了超類的一個(gè)方法族展,子類中的訪問(wèn)級(jí)別就不允許低于超類中的訪問(wèn)級(jí)別。這樣可以確保任何使用超類的實(shí)例的地方都可以使用子類的實(shí)例拔鹰。
接口中的方法默認(rèn)就是共有的仪缸,所以一個(gè)類實(shí)現(xiàn)了一個(gè)接口,那么接口中所有的類方法在這個(gè)類中也都必須聲明為公有的列肢。
實(shí)例域絕對(duì)不能是公有的(第14條:在公有類中使用訪問(wèn)方法而非公有域)恰画。
長(zhǎng)度非零的數(shù)組總是可變的,
public static final String[] VALUES = {};
//公有數(shù)組變成私有的瓷马,并增加一個(gè)公有的不可變列表
private static final String[] VALUES = {...};
public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
//或者返回私有數(shù)組的克隆
private static final String[] VALUES = {...};
public static final Thing[] values(){
return PRIVATE_VALUES.clone();
}
}
第14條:在公有類中使用訪問(wèn)方法而非公有域
如果類可以在它所在的包的外部進(jìn)行訪問(wèn)拴还,就提供訪問(wèn)方法,以保留將來(lái)改變?cè)擃惖膬?nèi)部表示法的靈活性欧聘。
如果類是包級(jí)私有的片林,或者私有的嵌套類,直接暴露它的數(shù)據(jù)域并沒(méi)有本質(zhì)的錯(cuò)誤怀骤。
第15條:使可變性最小化
不可變類只是其實(shí)例不能被修改的類费封,例如String,基本類型的包裝類蒋伦、BigInteger和BigDecimal弓摘。不可變的類比可變的類更加易于設(shè)計(jì)、實(shí)現(xiàn)和使用痕届。它們不容易出錯(cuò)韧献,且更加安全。
要使類成為不可變爷抓,要遵守下面五條規(guī)則:
1. 不要提供任何會(huì)修改對(duì)象狀態(tài)的方法势决。
2. 保證類不會(huì)被擴(kuò)展。一般是把類定義為final的蓝撇,或者將類的所有構(gòu)造器都變成私有的或者是包級(jí)私有的,并添加靜態(tài)工廠來(lái)代替共有的構(gòu)造器陈莽。
3. 使所有的域都是final的渤昌。
4. 使所有的域都成為私有的。
5. 確保對(duì)于任何可變組件的互斥訪問(wèn)走搁。確倍栏蹋客戶端無(wú)法獲得對(duì)象的引用。
不可變對(duì)象本質(zhì)上是線程安全的私植,它們不要求同步忌栅。
不可變對(duì)象可以被自由地共享,不僅可以共享不可變對(duì)象,甚至也可以共享它們的內(nèi)部信息索绪。
不可變對(duì)象為其他對(duì)象提供了大量的構(gòu)件
不可變對(duì)象真正唯一的缺點(diǎn)是湖员,對(duì)于每個(gè)不同的值都需要一個(gè)單獨(dú)的對(duì)象。
不可變的對(duì)象內(nèi)部可以擁有一個(gè)或者多個(gè)非final得域瑞驱,來(lái)緩存一些值(hashcode,String中就有)娘摔,不變形保證了這個(gè)值永遠(yuǎn)都不會(huì)變。
基本類型的域不能用final唤反,因?yàn)樵诔跏蓟臅r(shí)候凳寺,會(huì)被賦初始值。
第16條:復(fù)合優(yōu)先于繼承
本書使用的繼承指的是實(shí)現(xiàn)繼承彤侍,即一個(gè)類擴(kuò)展另一個(gè)類的時(shí)候肠缨。
繼承打破了封裝性。子類依賴超類的特定功能的實(shí)現(xiàn)盏阶,如果超類發(fā)生變化晒奕,子類必須跟著超類一起改變。這樣的子類是非常脆弱的般哼。
只有當(dāng)子類和超類之間確實(shí)存在子類型關(guān)系時(shí)(is-a)吴汪,使用繼承才是恰當(dāng)?shù)摹?/p>
第17條:要么為繼承而設(shè)計(jì),并提供文檔說(shuō)明蒸眠,要么就禁止繼承
文檔必須精確地描述覆蓋每個(gè)方法所帶來(lái)的影響漾橙。
對(duì)于每個(gè)公有的或者受保護(hù)的方法或者構(gòu)造器,它的文檔必須指明該方法或者構(gòu)造器調(diào)用了哪些可覆蓋的方法楞卡,是以什么順序調(diào)用的霜运,每個(gè)調(diào)用的結(jié)果又是如何影響后續(xù)的處理過(guò)程的。
好的API文檔應(yīng)該描述一個(gè)給定的方法做了什么工作蒋腮,而不是描述它是如何做到的淘捡。
為了繼承而設(shè)計(jì)的類,唯一的測(cè)試方法就是編寫子類池摧。
為了允許繼承焦除,類還必須遵守其他一些約束:
1.構(gòu)造器不能調(diào)用可被覆蓋的方法
2.如果為了繼承而設(shè)計(jì)的類實(shí)現(xiàn)了Cloneable或者Serializable接口,clone和readObject都不可以調(diào)用可覆蓋的方法作彤,不管是以直接還是間接的方式膘魄。
3.如果為了繼承而設(shè)計(jì)的類實(shí)現(xiàn)了Serializable接口,并且該類有一個(gè)readResolve或者writeReplace方法竭讳,就必須使readResolve或者writeReplace成為受保護(hù)的方法创葡,而不是私有的方法。
消除類中可覆蓋方法的自用特性绢慢。就可以安全的子類化灿渴。
第18條:接口優(yōu)于抽象類
1.現(xiàn)有的類可以很容易被更新,以實(shí)現(xiàn)新的接口。比如Comparable
2.接口是定義混合類型的理想選擇骚露〉偶罚混合類型表明具有某個(gè)可供選擇的行為。
3.接口允許我們構(gòu)造非層次結(jié)構(gòu)的類型框架荸百。
骨架實(shí)現(xiàn)類就是一個(gè)抽象類繼承了某一個(gè)接口
第19條:接口只用于定義類型
常量接口:沒(méi)有包含任何方法闻伶,只包含了一些靜態(tài)的final域,每個(gè)域都導(dǎo)出一個(gè)常量够话。常量模式是對(duì)接口的不良使用
如果要導(dǎo)出常量蓝翰,就應(yīng)該把這些常量添加到這個(gè)類。
使用枚舉類型或者不可實(shí)例化的工具類女嘲。
第20條:類層次優(yōu)于標(biāo)簽類
類層次可以反映類型之間本質(zhì)上的層次關(guān)系畜份。
第21條:用函數(shù)對(duì)象表示策略
函數(shù)指針的只要用途就是實(shí)現(xiàn)策略模式。
在java中實(shí)現(xiàn)這種模式欣尼,首先要聲明一個(gè)接口來(lái)表示該策略爆雹,并且為每個(gè)具體策略聲明一個(gè)實(shí)現(xiàn)了該接口的類。當(dāng)一個(gè)具體策略只被調(diào)用一次的時(shí)候愕鼓,通常使用匿名類來(lái)聲明和實(shí)例化這個(gè)具體的實(shí)現(xiàn)類钙态。當(dāng)一個(gè)具體策略是設(shè)計(jì)用來(lái)重復(fù)使用的時(shí)候,它的類通常就要被實(shí)現(xiàn)為私有的靜態(tài)成員類菇晃,并通過(guò)公有的靜態(tài)final域被導(dǎo)出册倒,其類型為該策略接口。
第22條:優(yōu)先考慮靜態(tài)成員類
見(jiàn)另一篇文章《Java嵌套類》磺送。