簡體   English   中英

Java中包私有類的優缺點?

[英]Pros and cons of package private classes in Java?

我最近在學習Java,我遇到了package-private類的概念,如果我們沒有指定任何東西,這是默認的。 但后來我意識到:

  1. 我很少看到使用package-private類。 是否有這樣的原因,例如,它有嚴重的缺點,它是多余的,或者只是我讀得不夠? 是否有強烈的論據支持/反對其使用?

  2. 如果它在大多數情況下確實沒用,為什么它會是默認值?

  3. 在什么情況下我們應該在現實世界中使用package-private? 即,什么時候會變得不可替代?

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

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

我假設您熟悉publicprivate之間的區別,以及為什么將方法和變量設置為private的通常是好的做法,如果它們將僅在內部用於相關類。

好吧,作為對此的擴展 - 如果您正在考慮以模塊化方式創建軟件,您可能會想到一個模塊的公共接口,它將在其中有多個類在它們之間進行協作。 在這種情況下,如果方法被消費者調用,那么將方法public是完全合理的; private如果他們是班級內部的; 如果它們習慣於在這個模塊中的類之間調用,那么它們就是package private ,即它是模塊的實現細節(公共調用者可以看到),但是跨越了幾個類。

這在實踐中很少使用,因為包裝系統對於這種事情並沒有那么有用。 您必須將給定模塊的所有類轉儲到完全相同的包中,對於任何非平凡的包都會變得有點笨拙。 所以這個想法很棒 - 只需要一些“附近”的類就可以訪問一個方法,作為一個稍微寬泛的private - 但是如何定義這組類的限制意味着它很少使用/有用。

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

除了封裝之外,使用package-private類的一個主要優點是它們不會出現在項目的javadoc中。 因此,如果您使用一些沒有其他用途的幫助程序類,但是為了幫助您的公共類執行客戶需要的操作,那么將它們打包為私有是有意義的,因為您希望為庫的用戶保持盡可能簡單。

例如,您可以查看我開發的庫。 javadoc只包含5個接口和12個類,盡管源代碼還有很多。 但隱藏的主要是內部層,它們不為客戶端提供任何附加值(通常隱藏所有抽象基類)。

JDK中也有很多例子。

包私有訪問級別比protected保護更嚴格:仍然可以通過簡單地繼承類來訪問受保護的屬性和方法。 受保護的成員是(或可能)用於繼承而package-private成員不是。

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

這方面的好例子是String的package-private構造函數和StringBuilder.value char數組:

/*
* 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;
}

因此,如果內容已經存在於char[]而不影響安全性,則java.lang包中的類可以有效地創建新的Strings 您不能從您的應用程序執行此操作,因為如果可以,您將訪問(引用) String的內部char數組,該String是不可變的(反射不計算!)。

StringBuilder (或者更確切地說是AbstractStringBuilder ,其實現來自)中,保存當前值char[] value的char數組和此char[] getValue()的訪問器方法也是包私有的,因此String各種實用方法如contentEquals(StringBuffer sb)contentEquals(CharSequence cs)可以利用它來提高效率和更快的比較,而不會將內部char數組暴露給“世界”。

關於“為什么會是默認”的問題,在這種情況下,“默認”一詞僅僅意味着缺少另一個限定詞。 我猜他們本可以發明另一個關鍵詞(已經采用了“包”),但他們沒有。

在現實世界中,我使用默認訪問實用程序類和抽象類,我不希望人們調用或以其他方式使用其他包。 假設您有一個接口和兩個具體實現,它們從一些抽象類擴展而來。 您將兩個具體類聲明為final,因為您不一定希望人們將它們子類化(請參閱Effective Java)。 出於同樣的原因,你也不希望人們在你的抽象類中閑逛。 如果您對抽象類使用默認訪問權限,那么只有當他們將類放在您的包中時,人們才會看到它。 它不是防彈,但我認為它是默認訪問的合理使用/說明。 也就是說,它不會阻止細節泄露為私有,即不保證任何東西,這意味着它不是一個特別有用的約定。

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

1 - 取決於架構 - 一般如果你只為自己和小項目編寫代碼,你可能不會使用它。 在較大的項目中,確保您可以控制某些方法的調用位置和方式可能會有所幫助。

2 - 默認(即不公開/保護/私人)與私人不同 - 它是第4個州。 請參閱Java Access Control

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

請注意,當您談論課程時,您只有兩種選擇:

  1. 公共課
  2. 包私人課程

“私人階級”的概念毫無意義。 (為什么要創建一個沒有在任何地方使用的類?!)

因此,如果您有一個不需要向API用戶公開的中間操作的類,您應該將其聲明為“包私有”

此外,當您在同一源文件中定義許多類時,只允許一個類是公共的(其名稱與.java文件名匹配)。 如果在同一文件中定義了任何其他類,則它必須是“package private”。

“包私有”,當你有多個包時使用它,這意味着,同一個包中的其他類可以訪問該類或類成員為“public”,其他包中的類無法訪問,就像“像他們一樣私有”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM