私はJava最近学習しており、package-private
クラス。これは何も指定しない場合のデフォルトです。しかし、その後、私は気づいた:
パッケージプライベートクラスの使用はめったにありません。これには理由がありますか?たとえば、深刻な欠点がある、冗長である、または単に十分に読んでいないのですか?その使用に対する/反対の強い議論はありますか?
ほとんどの場合、それが実際に役に立たない場合、なぜそれがデフォルトになるのでしょうか?
現実の状況では、どのような状況でpackage-privateを使用する必要がありますか?つまり、いつそれがかけがえのないものになるのでしょうか?
つまり、デフォルトのpackage-private修飾子の主な長所と短所は何ですか?
短い答えは-プライベートの少し広い形式です。
public
とprivate
の違いに精通していること、そしてメソッドと変数を作成するのが一般的に良い習慣であると仮定しますprivate
問題のクラスの内部でのみ使用されます。
まあ、それの拡張として-モジュール方式でソフトウェアを作成することを考えているなら、moduleへのパブリックインターフェイスを考えるかもしれません。 。このコンテキストでは、コンシューマーによって呼び出される場合は、メソッドpublic
を作成するのが最適です。 private
(クラスの内部にある場合)。およびpackage private
このモジュールのクラス間での呼び出しに使用されている場合、つまり、モジュールの実装の詳細(公開呼び出し側から見た場合)ですが、いくつかのクラスにまたがっています。
パッケージシステムはこの種のことにあまり役に立たないことが判明したため、これは実際にはめったに使用されません。特定のモジュールのすべてのクラスをまったく同じパッケージにダンプする必要がありますが、これは些細なことでは少し扱いにくいものになります。アイデアは素晴らしいです-少し広いprivate
として、ほんの一握りの「近くの」クラスにアクセスできるメソッドを作成します-しかし、そのクラスのセットを定義する方法の制限は、それがめったに使用されない/有用であることを意味します。
Package-privateの良い点の1つは、それを使用して、単体テストクラスでプライベートと見なされるメソッドにアクセスできることです。もちろん、パッケージ内の他のクラスは、本来すべきではないときに呼び出すことができるという欠点があります。
カプセル化とは別に、パッケージプライベートクラスを使用する主な利点の1つは、プロジェクトのjavadocに表示されないことです。したがって、他の用途のないヘルパークラスを使用するが、パブリッククラスがクライアントが必要とする何かを行うのを支援するために、ライブラリのユーザーができる限りシンプルにしたいので、それらをプライベートにすると意味があります。
例として、私が開発したライブラリを見ることができます。 javadoc には5つのインターフェースと12のクラスしか含まれていませんが、 ソースコード にはさらに多くのものがあります。しかし、隠されているのは主に、クライアントに付加価値を提供しない内部層です(通常、すべての抽象基本クラスは隠されています)。
JDKには多くの例もあります。
パッケージプライベートアクセスレベルはprotected
よりも制限的です。保護された属性とメソッドは、クラスをサブクラス化するだけでアクセスできます。 Protectedメンバーは継承を目的としています(または可能性があります)が、パッケージプライベートメンバーはそうではありません。
パッケージプライベートメンバーがよく使用されるため、パッケージ内のマルチループクラスは実装固有属性または(ユーティリティ)メソッドにアクセスできます。
これの良い例は、String
のパッケージプライベートコンストラクターと_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;
}
_
したがって、_Java.lang
_パッケージ内のクラスは、コンテンツが既に_char[]
_に存在する場合、セキュリティを損なうことなく、新しいStrings
を効率的に作成できます。アプリケーションからこれを行うことはできません。可能な場合は、String
の内部char配列にアクセス(参照)できるため、不変です(リフレクションはカウントされません!)。
StringBuilder
(または実装の元となるAbstractStringBuilder
)では、現在の値_char[] value
_を保持するchar配列と、このchar[] getValue()
へのアクセサーメソッドもパッケージです。 -privateなので、contentEquals(StringBuffer sb)
やcontentEquals(CharSequence cs)
のようなString
のさまざまなユーティリティメソッドは、内部char配列を「世界」に公開せずに効率と高速比較のためにこれを利用できます。
「なぜデフォルトになるのか」という質問に関しては、このコンテキストでは、「デフォルト」という用語は別の修飾子がないことを意味します。彼らは別のキーワードを発明することができたと思います(「パッケージ」はすでに採用されていました)が、そうではありませんでした。
現実の世界では、他のパッケージから呼び出したり使用したりしたくないユーティリティクラスと抽象クラスにデフォルトのアクセスを使用します。ある抽象クラスから拡張されたインターフェイスと2つの具体的な実装があるとします。 2つの具象クラスをfinalとして宣言するのは、必ずしも人々にサブクラスをサブクラスにしたくないからです(「効果的なJava」を参照)。また、同じ理由で、人々が抽象クラスで動き回ることを望まない。抽象クラスにデフォルトのアクセスを使用する場合、人々は自分のクラスをパッケージに入れた場合にのみそれを見ることができます。これは完全な証拠ではありませんが、デフォルトのアクセスの合理的な使用/説明だと思います。つまり、プライベートのように詳細が漏洩するのを防止しない、つまり何も保証しないという事実は、特に有用な慣習ではないことを意味します。
頻繁に使用されていないもう1つの理由は、javadocsからデフォルトのアクセス権を持つクラスを除外する傾向があることです。
1-アーキテクチャに依存します-一般的に、自分用にコードを書いている場合や小さなプロジェクトでは、おそらくそれを使用しないでしょう。大規模なプロジェクトでは、特定のメソッドをどこでどのように呼び出すかを確実に制御できると便利です。
2-デフォルト(つまり、public/protected/privateではない)はprivateとは異なります-その4番目の状態。 Java Access Control を参照してください
3-基盤となるコードの実装方法に依存するサードパーティを望まないライブラリを作成する場合、API自体を公開するだけで、作業が楽になります。
クラスについて話すとき、2つのオプションしかありません。
「プライベートクラス」の概念は無意味です。 (どこでも使用されないクラスを作成する理由は!?)
したがって、APIユーザーに公開する必要のない中間操作のクラスがある場合、「パッケージプライベート」として宣言することになっています。
また、同じソースファイルで多くのクラスを定義する場合、1つのクラスのみがパブリックになります(その名前は.Javaファイル名と一致します)。同じファイルで他のクラスが定義されている場合、「パッケージプライベート」である必要があります。