2011-06-24 65 views
49

我最近在學習Java,並且遇到了package-private類的概念,如果我們沒有指定任何內容,這是默認的。但後來我意識到:Java中包私有類的優缺點?

  1. 我很少看到使用包私有類。是否有這樣的理由,例如,它有嚴重的缺點,是多餘的,還是僅僅是我讀得不夠?是否有強烈的爭論/反對它的用法?

  2. 如果在大多數情況下它確實沒有用,爲什麼它會成爲默認值?

  3. 在什麼情況下我們應該在現實世界中使用package-private?也就是說,它何時會成爲不可替代的?

換句話說,默認package-private修飾符的主要優點和缺點是什麼?

回答

41

簡短的回答是 - 這是一個稍寬的私人形式。

我假設你熟悉publicprivate之間的區別,以及爲什麼它通常是很好的做法,使方法和變量private,如果他們要單獨用於內部問題的類。

那麼,作爲一個擴展, - 如果你想在一個模塊化的方式建立你的軟件,你可能會想到一個公共接口你模塊,這將有多個類裏面彼此之間的合作。在這種情況下,如果消費者打電話給他們,製作方法public就很有意義; private如果它們是一個班級的內部;和package private,如果它們用於在此模塊中的類之間調用,即它是模塊的實現細節(如公共調用者所見),但跨越多個類。

這在實踐中很少使用,因爲包裝系統對於這類事情並不那麼有用。你必須將給定模塊的所有類轉儲到完全相同的包中,這對於任何不重要的東西都會變得笨拙。所以這個想法非常棒 - 只需少量的「附近」類就可以訪問一個方法,稍微寬一些,但是對於如何定義這些類的限制意味着它很少被使用/很有用。

+1

我可以看到爲什麼有人可能會這麼說 - 'protected'修飾符與'package private'相同,除了子類也被邀請參加聚會。但是如果不是自然存在的話,創建子類關係(僅用於訪問目的)會是錯誤的。它通常不會對例如一個EmailSender類是DomainObjectFilter類的一個子類,反之亦然。在這種情況下,這種方法通常只是「公開」(可能有一條評論說它不在概念上是公開的)。 –

+0

「將給定模塊的所有類轉儲到完全相同的包中 - 不易操作」 - 正確,但我甚至在非平凡的情況下使用了這種方法,例如20-30個包裝類。當然,任何更大的東西都需要重構。 –

+0

難道你不能將源文件組織到一個目錄層次結構中,然後在編譯之前將它們全部轉儲到同一個目錄/包中?那會給你組織結構和包私人訪問的好處,對嗎? – jrahhali

1

1 - 取決於體系結構 - 一般情況下,如果您只是爲自己編寫代碼,而在小型項目中編寫代碼,則可能不會使用它。在較大的項目中,確保您可以控制何處以及如何調用某些方法會很有幫助。

2 - 默認(即不公開/保護/私人)不是私有 - 它是第四個狀態。請參閱Java Access Control

3 - 當您編寫不想讓第三方依賴於您如何實現底層代碼的庫時,它可以使生活更輕鬆 - 您只需將API本身公開。

+0

@BZ是不是默認包私人? –

+2

http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html –

+1

@BZ其中說:如果一個類沒有修飾符(默認,也稱爲package-private)。感謝您的答案,術語是微不足道的:) –

2

關於「爲什麼會是默認值」的問題,在這種情況下,術語「默認」僅僅意味着沒有另一個限定符。我猜他們可能已經發明瞭另一個關鍵字(「包裹」已被採用),但他們沒有。

在現實世界中,我使用默認訪問實用程序類和抽象類,我不希望人們調用或以其他方式使用其他包。假設您有一個接口和兩個具體的實現,它們從一些抽象類擴展而來。你聲明你的兩個具體類是最終的,因爲你不一定希望人們繼承它們(見Effective Java)。你也不希望人們出於同樣的原因在你的抽象類中四處閒逛。如果您對抽象類使用默認訪問權限,那麼只有在他們的類放入您的包中時,人們纔會看到它。這不是防彈的,但我認爲這是對默認訪問的合理使用/說明。也就是說,這並不妨礙細節泄露,因爲它並不保證任何內容,這意味着它不是一個特別有用的慣例。

爲什麼你沒有看到它更經常使用的另一個原因是人們傾向於從javadocs中排除具有默認訪問權限的類。

+0

他不會誤解術語「默認」,他會問爲什麼這是默認訪問級別。默認的一個原因是最經常使用的東西。還有其他原因,他正在要求他們。 –

+1

我不確定您是否正確,但我很樂意爲清晰度更新回覆。 – jtoberon

-1

「包私人」它使用時,你有幾個包,也就是說,在同一包中的其他類可以訪問該類或類成員爲「公共」,其他包中的類不能訪問,就像「私人喜歡他們。」

9

package-private的一個好處是你可以使用它來訪問你認爲私有的單元測試類的方法。當然,其缺點是包中的其他類可以在它們不應該的時候調用它。

0

請注意,當你在談論類你只有兩個選擇:

  1. 公共類
  2. 包私有類

的「私有類」的概念是沒有意義的。 (爲什麼做未在任何地方使用的一類?)

所以,如果你有需要不被暴露於API用戶中間操作的類,你應該將其聲明爲「包私人」

另外,當您在同一個源文件中定義多個類時,只允許一個類爲public(其名稱與.java文件名相匹配)。如果在同一個文件中定義了任何其他類,則它必須是「私有包」。

2

除封裝之外,使用包私有類的主要優點之一是它們不會出現在項目的javadoc中。因此,如果您使用一些除此之外沒有其他用途的幫助程序類,它們可以幫助您的公共類實現客戶需要的某些功能,那麼將它們打包爲私有程序是有意義的,因爲您希望爲圖書館用戶儘可能簡化事務。

作爲一個例子,你可以看看我開發的庫。 javadoc只包含5個接口和12個類,儘管source code有更多。但是隱藏的內容大多是內部層,它不爲客戶端提供附加價值(通常所有的抽象基類都是隱藏的)。

在JDK中也有很多例子。

0

程序包專用訪問級別比protected更受限制:受保護的屬性和方法仍然可以通過簡單繼承類來訪問。 受保護的成員是(或可能)用於繼承,而包私有成員則不是。

通常使用包私有成員,因此包內的多重類可以訪問實現特定的屬性或(實用程序)方法。

來就是很好的例子是String的包私有的構造和StringBuilder.value字符數組:

/* 
* Package private constructor which shares value array for speed. 
* this constructor is always expected to be called with share==true. 
* a separate constructor is needed because we already have a public 
* String(char[]) constructor that makes a copy of the given char[]. 
*/ 
String(char[] value, boolean share) { 
    // assert share : "unshared not supported"; 
    this.value = value; 
} 

所以java.lang包中的類可以高效地創建新Strings如果內容已經存在於char[]無危及安全。你不能在你的應用程序中這樣做,因爲如果可以的話,你可以訪問(引用)到String的內部char數組,這是不可變的(反射不算!)。

StringBuilder(或更確切地說AbstractStringBuilder其中執行來自)char數組保持的電流值char[] value和存取方法本char[] getValue()也包私人的String所以各種實用程序的方法,如contentEquals(StringBuffer sb)contentEquals(CharSequence cs)可以利用該對效率和快速比較,而不會將內部字符數組暴露給「世界」。