- 訪問(wèn)控制(或隱藏具體實(shí)現(xiàn))與“最初的實(shí)現(xiàn)并不恰當(dāng)”有關(guān)。
- 重構(gòu)即重寫(xiě)代碼,以使得它更可讀,更容易理解,并因此而更具維護(hù)性。
- 在面向?qū)ο笤O(shè)計(jì)中需要考慮一個(gè)基本問(wèn)題:“如何把變動(dòng)的事物與保持不變的事物區(qū)分開(kāi)來(lái)”
- 應(yīng)該盡可能將一切方法都定為
private,而僅向客戶端程序員公開(kāi)你愿意讓他們使用的方法。
包:庫(kù)單元
- 包內(nèi)包含有一組類(lèi),它們?cè)趩我坏拿挚臻g之下被組織在一起
- 為了解決潛在的名字沖突問(wèn)題,Java使用 package 對(duì)名稱(chēng)空間進(jìn)行完全控制并為每一個(gè)類(lèi)創(chuàng)建唯一的標(biāo)識(shí)符組合。
- 每一個(gè)編譯單元(.java 文件)只能有一個(gè) public 類(lèi)。
- 當(dāng)編譯一個(gè) Java 文件時(shí),.java 文件中的每一個(gè)類(lèi)都會(huì)生成一個(gè)與其類(lèi)名相同的 .class 文件
- Java 可運(yùn)行程序是一組可以打包并壓縮為一個(gè) Java 文檔文件(JAR)的 .class 文件,Java解釋器負(fù)責(zé)這些文件的查找、裝載和解釋。
- 類(lèi)庫(kù)實(shí)際上一組類(lèi)文件。其中每個(gè)文件都有一個(gè) public 類(lèi),以及任意數(shù)量的非 public 類(lèi)。因此每個(gè)文件都有一個(gè)構(gòu)件,如果希望他們都屬于同一個(gè)群組,則可以使用關(guān)鍵詞 package。
- package 語(yǔ)句必須是文件中除了注釋外的第一行代碼。如
packgae access;表示當(dāng)前文件是 access 類(lèi)庫(kù)的一部分,標(biāo)識(shí)符為access.ClassName; - package 名稱(chēng)的第一部分應(yīng)該是域名的逆序。
- package 名稱(chēng)會(huì)被分解為一個(gè)目錄路徑,這個(gè)包的所有文件都應(yīng)該放在該文件夾中,例如包名為
fun.wuxiaobai24.access,則被解釋成$CLASSPATH/fun/wuxiaobai24/access,其中$CLASSPATH為環(huán)境變量,CLASSPATH 可以指定多個(gè)目錄。 - 在使用JAR文件時(shí),需要在 CLASSPATH 中指明JAR文件的真實(shí)路徑,如
CLASSPATH = .;~/jar/access.jar - 如果將兩個(gè)包含相同名稱(chēng)的類(lèi)庫(kù)用
*形式導(dǎo)入時(shí),在使用重名的類(lèi)時(shí),需要指明是那個(gè)包中的,如fun.wuxiaobai24.access.ClassName c = new fun.wuxiaobai24.access.ClassName() - 使用
import static語(yǔ)句進(jìn)行靜態(tài)導(dǎo)入,將某個(gè)包中的所有靜態(tài)方法導(dǎo)入,這樣可以直接用靜態(tài)方法名進(jìn)行方法調(diào)用,而不用在前面加類(lèi)名,如調(diào)用某個(gè)類(lèi)中的 main() 方法時(shí),靜態(tài)導(dǎo)入可以直接main();,而普通的導(dǎo)入而需要ClassName.main(); - Java 中 沒(méi)有 C 中的條件編譯,但是可以用 import 來(lái)間接實(shí)現(xiàn)某些功能。
Java 訪問(wèn)權(quán)限修飾詞
- 包訪問(wèn)權(quán)限允許將包內(nèi)所有相關(guān)的類(lèi)組合在一起,以使得它們彼此之間可以相互訪問(wèn)作用。
- 繼承而來(lái)的類(lèi)可以訪問(wèn)
public和protected,只有當(dāng)兩個(gè)類(lèi)在同一個(gè)包中時(shí)才能訪問(wèn)包訪問(wèn)權(quán)限的成員。 - 對(duì)于OOP而言,提供訪問(wèn)器和變異器(getter/setter),以讀取或改變數(shù)值是最優(yōu)雅的方法,而是 JavaBean 的基本原理。
- 如果沒(méi)有給文件指定包,Java 將這些文件視為該目錄的默認(rèn)包中,于是給該目錄中所有其他的文件提供包訪問(wèn)權(quán)限。
- 不能因?yàn)樵陬?lèi)中某個(gè)對(duì)象的引用是 private,就認(rèn)為其他對(duì)象就不能擁有該對(duì)象。
- protected 成員除了繼承的子類(lèi)可以訪問(wèn)外,它也有包訪問(wèn)權(quán)限,即同一個(gè)包下的類(lèi)可以訪問(wèn)它。
- private 可以用來(lái)實(shí)現(xiàn)單例子模式:
class Soup {
private Soup() {}
private static Soup soup = new Soup();
public static Soup access() {
return soup;
}
}
接口和實(shí)現(xiàn)
訪問(wèn)權(quán)限的控制常被稱(chēng)為具體實(shí)現(xiàn)的隱藏。把數(shù)據(jù)和方法包裝進(jìn)類(lèi)中,以及具體的實(shí)現(xiàn)的隱藏,常共同被稱(chēng)為封裝。其結(jié)果是一個(gè)同時(shí)帶有特征和行為的數(shù)據(jù)類(lèi)型。
訪問(wèn)權(quán)限控制將權(quán)限的邊界劃在數(shù)據(jù)類(lèi)型的內(nèi)部的原因:
- 不用擔(dān)心客戶端程序員偶然地將內(nèi)部機(jī)制當(dāng)作他們可以使用的接口的一部分。
- 接口和具體實(shí)現(xiàn)的分離
類(lèi)的訪問(wèn)權(quán)限
為了控制類(lèi)的訪問(wèn)權(quán)限,修飾詞必須出現(xiàn)在關(guān)鍵詞 class 之前,如public class ClassName。同時(shí)有一些額外的限制:
- 每個(gè)編譯單元(文件)都只能有一個(gè) public 類(lèi)。每個(gè)編譯單元都有單一的公共接口,同 public 類(lèi)實(shí)現(xiàn)
- public 類(lèi)的名稱(chēng)必須與文件名相同,包括大小寫(xiě)。
- 編譯單元(文件)中可以完全不帶 public 類(lèi),此時(shí)可以隨意對(duì)文件命名。
類(lèi)的訪問(wèn)權(quán)限只有 public 和包訪問(wèn)權(quán)限。如果希望其他任何人對(duì)該類(lèi)有訪問(wèn)權(quán)限,可以將所有的構(gòu)造器都指定為 private,但是該類(lèi)中 static 成員仍然可以創(chuàng)建和訪問(wèn)。
本文首發(fā)于Code & Fun