- 設(shè)計(jì)良好的模塊會(huì)隱藏所有的實(shí)現(xiàn)細(xì)節(jié)谍失,會(huì)把實(shí)現(xiàn)細(xì)節(jié)與它的API清晰的隔離開(kāi)來(lái)拌滋,模塊之間只通過(guò)它們的API進(jìn)行通信哥谷,一個(gè)模塊不需知道其他模塊的內(nèi)部工作情況。這個(gè)概念被稱為信息隱藏(information hiding)或封裝(encapsulation)瓶堕。
1. 四種訪問(wèn)級(jí)別
關(guān)鍵字 | 描述 |
---|---|
private | 只有在聲明該成員的頂層類內(nèi)部才可以訪問(wèn)這個(gè)成員 |
package-private (default) | 聲明該成員的包的內(nèi)部的任何類都可以訪問(wèn)這個(gè)成員 |
protected | 聲明該成員的類的子類可以訪問(wèn)這個(gè)成員隘道,并且聲明該成員的包內(nèi)部的任何類也可以訪問(wèn)這個(gè)成員 |
public | 任何地方都可以訪問(wèn)該成員 |
2. 訪問(wèn)控制機(jī)制
- 訪問(wèn)控制機(jī)制決定了類、接口和成員的可訪問(wèn)性(accessibility)郎笆;
- 盡可能地使每個(gè)類或者成員不被外界訪問(wèn)谭梗,對(duì)于頂層的(非嵌套的)類和接口,只有兩種可能的訪問(wèn)級(jí)別:包級(jí)私有的(package-private)和公有的(public)宛蚓;
- 如果一個(gè)包級(jí)私有的頂層類(或者接口)只是在某一個(gè)類的內(nèi)部被用到激捏,就應(yīng)該考慮使它成為唯一使用它的那個(gè)類的私有嵌套類;
- 只有當(dāng)同一個(gè)包內(nèi)的另一個(gè)類真正需要訪問(wèn)一個(gè)成員的時(shí)候凄吏,你才應(yīng)該刪除private修飾符远舅,使該成員成為包級(jí)私有的。
- 如果方法覆蓋了超類中的一個(gè)方法竞思,子類中的訪問(wèn)級(jí)別就不允許低于超類中的訪問(wèn)級(jí)別表谊;(特殊:如果一個(gè)類實(shí)現(xiàn)了一個(gè)接口钞护,那么接口中所有的類方法在這個(gè)類中也都必須被生命為公有的盖喷,接口中所有方法都隱含著共有訪問(wèn)級(jí)別)
- 實(shí)例域中,包含共有可變域的類并不是線程安全的难咕;
- 靜態(tài)域中课梳,假設(shè)常量構(gòu)成類類提供的整個(gè)抽象中的一部分,可以通過(guò)共有的靜態(tài)final域來(lái)暴露這些常量余佃,由大寫(xiě)字母組成單詞之間用下劃線隔開(kāi)暮刃。很重要一點(diǎn),這些域要么包含基本類型的值爆土,要么包含指向不可變對(duì)象的引用椭懊。
注:長(zhǎng)度非零的數(shù)組總是可變的,類具有共有的靜態(tài)final數(shù)組域步势,或者返回這種域的訪問(wèn)方法氧猬,幾乎總是錯(cuò)誤的。這是安全漏洞的一個(gè)常見(jiàn)根源:
// Potential security hole!
public static fianl Thing[] VALUES = { … }坏瘩;
修正方法:
- 公有數(shù)組變?yōu)樗接械闹迅В⒃黾右粋€(gè)公有的不可變列別:
private static final Thing[] PRIVATE_VALUES = { … };
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asLIst(PRIVATE_VALUES));
- 使數(shù)組變成私有的,并添加一個(gè)公有方法倔矾,它返回私有數(shù)組的一個(gè)備份
private static final Thing[] PRIVATE_VALUES = { … };
public static fianl Thing[] values() {
return PRIVATE_VALUES.clone();
}
總結(jié):應(yīng)該盡可能地降低可訪問(wèn)性妄均。在仔細(xì)地設(shè)計(jì)一個(gè)最小的公有API之后柱锹,應(yīng)該防止把任何散亂的類、接口和成員變成API的一部分丰包,除公有靜態(tài)final域的特殊情形之外禁熏,共有類都不應(yīng)該包含公有域,并且要確保公有靜態(tài)final域所引用的對(duì)象都不是可變的烫沙。