クラスオブジェクトのgetPackageメソッドを呼び出すと、クラスが配置されているパッケージを説明するパッケージオブジェクトを取得できます(パッケージクラスはjava.langで定義されています)。また、静的メソッドGetPackageを呼び出すか、静的メソッドGetPackages(システム内のすべての既知のパッケージで構成される配列を返す)を呼び出すことにより、パッケージ名を使用してパッケージオブジェクトを取得することもできます。 getNameメソッドは、パッケージのフルネームを返すことができます。
パッケージオブジェクトの使用は、他の反射タイプとはまったく異なります。つまり、実行時にパッケージを作成または操作することはできません。パッケージオブジェクトを使用して、パッケージの目的、パッケージ、パッケージのバージョンなどなど、パッケージに関する情報を取得できます。これらのコンテンツを後で詳細に説明するまで延期します。
パッケージの命名
パッケージ名は他のパッケージとの競合を避ける必要があるため、意味のあるもので一意の両方の名前を選択することは、パッケージデザインの重要な側面です。ただし、世界中のプログラマーがパッケージを開発しており、誰がパッケージ名を使用したかを知る方法はないため、唯一のパッケージ名を選択することは問題です。パッケージが組織内でのみ使用されていると判断した場合、プロジェクト間に名前の競合がないことを確認するために、内部アービターを持つことができます。
しかし、全世界では、このアプローチは実用的ではありません。パッケージ識別子はすべて簡単な名前であり、パッケージ名がインターネットドメイン名を使用することを確認するためのより良い方法です。私たちが働いている会社が魔法です。lncで、会社のドメイン名がMagic C.comである場合、属性パッケージの宣言は次のとおりです。
パッケージcom.magic.attr;
ここのドメイン名構成要素は、従来のドメイン名の逆順序で配置されていることに注意してください。
このイディオムを採用した場合、使用するパッケージ名は、組織内の競合の可能性を除いて、他の人と矛盾しません。私たちの組織内に実際に対立がある場合(おそらく大企業)、より具体的なドメイン名を使用してさらに資格を得ることができます。多くの大企業には、東部やヨーロッパなどの内部サブドメインがあります。これらは、パッケージの名前をさらに修飾するために使用できます。
パッケージcorn.magic.japan.attr;
このソリューションを使用すると、パッケージ名が非常に長くなる可能性がありますが、比較的安全です。この手法を使用するプログラマは同じパッケージ名を選択しません。この手法を使用しないプログラマーは、使用する名前を選択しません。
パッケージコンテンツ
パッケージの内容は、機能的に関連するクラスとインターフェイスのみを含めるように慎重に設計する必要があります。パッケージ内のクラスは、パッケージ内の他のクラスの非プライベートメンバー以外のメンバーに自由にアクセスでき、一部のクラスでは、他のクラスの内部詳細にアクセスするのに十分な許可がある場合さえあります。このようなクラスがクラスメンバーを誤って操作することを避けるために、クラスメンバーを保護する必要があります。プライベートとして宣言されていないメンバーは、同じパッケージ内の他のすべてのタイプからアクセスできるため、無関係なクラスは予想よりも調整される可能性が高くなる可能性があります。
パッケージは、便利なインターフェイスとクラスを探しているプログラマーに論理的なグループ化も提供します。無関係なクラスで構成されるパッケージにより、プログラマーはどのインターフェイスとクラスが有用であるかをプログラマーが伝えることを困難にし、クラスの論理グループ化はプログラマーがコードを再利用するのに役立ちます。パッケージに関連する、しっかりと結合されたタイプセットのみが含まれている場合、名前の競合を避けるために、より直感的な名前を型に与えることができます。
パッケージはネストできます。たとえば、Java.Langはネストされたパッケージであり、パッケージLangがより大きなパッケージJavaにネストされていますが、パッケージJ AVAには他のパッケージも含まれています。ネスティングにより、関連するパッケージが階層構造を備えた命名システムを形成します。
たとえば、ニューラルネットワークや遺伝的アルゴリズムなどの適応システム用のパッケージのセットを作成するには、ドット分離名のパッケージに名前を付けてネストされたパッケージを作成できます。
パッケージアダプティブ。ニューラルネット;
上記の宣言ステートメントを含むソースファイルは、adaptive.neuralnetパッケージにあり、adaptive.neuralnetパッケージ自体は適応パッケージのサブパッケージです。適応パッケージには、一般化問題ステートメントクラスやベンチマーククラスなど、一般的な適応アルゴリズムに関連するいくつかのクラスが含まれる場合があります。階層のより深い位置にあるパッケージ(Adaptive.neu-LarnetまたはAdaptive.genetic)には、特定のタイプの適応アルゴリズムに関連するクラスが含まれています。
パッケージのネストは、関連するパッケージを整理するためのツールにすぎません。パッケージ間で特別なアクセス権は提供されません。
Adaptive.geneticパッケージのクラスコードは、パッケージアクセス権を持つAdaptiveまたはAdaptive.neuralNetパッケージのメンバーにアクセスできず、パッケージスコープは特定のパッケージにのみ適用できます。パッケージのネストは、関連するパッケージをグループ化することができ、プログラマーが論理レベルで望ましいクラスをより便利に見つけるのに役立ちますが、それを超えて、他の利点をもたらすことはありません。
パッケージノート
パッケージには注釈も付けることができます。しかし、問題は、パッケージはソースコードエンティティのない組織構造であり、実際の定義がないため、クラスやメソッドのように注釈を付けることができないため、パッケージの注釈はソースファイルでパッケージの宣言ステートメントを注釈することによってのみ達成できることです。ただし、各パッケージには、その上に作用する注釈を持つことができるパッケージ宣言は1つだけです。
では、どのようにパッケージに注釈を付けますか?実際、Javaは、プログラマーが「単一の注釈付きパッケージステートメント」ルールに対処するための何らかの方法を使用することを強制しません。推奨される方法は、パッケージディレクトリにPackage-I nfo.javaという名前のファイルを作成することです。パッケージステートメントとパッケージの注釈のみが他のものを配置せずに保存されます。たとえば、attrパッケージのパッケージinfo.javaファイルは次のようになります。
@PackagesPec(2つの「attrプロジェクト」、バージョン= "1.0" @developmentsite( "attr.project.org")@developmentModel( "open-source")パッケージattr;
PackagesPec、DevelopmentSite、および開発OpmentModelは、注釈タイプを変更するために使用されます。もちろん、彼らはランタイム節約戦略を持っています。パッケージinfo.javaファイルは、パッケージ内の他のソースファイルとコンパイルする必要があります。
パッケージ関連のすべての情報をパッケージinfo.javaファイルに配置することをお勧めします。これを行うと、ファイルの先頭にドキュメントコメントを配置して、これらのドキュメントにパッケージドキュメントとして注釈が付けられます。
パッケージアクセス
パッケージ内のトップレベルのクラスとトップレベルのインターフェイスのアクセシビリティを宣言する場合、パッケージアクセス(パッケージ)とパブリックアクセス(パブリック)の2つのオプションがあります。一般に変更されたクラスまたはインターフェイスには、パッケージ外のコードでアクセスできますが、公開されていないタイプにはパッケージスコープがあります。同じパッケージの他のコードでアクセスできます。ただし、サブパッケージコードであっても、パッケージ外のコードのために隠されています。タイプを宣言する場合、他のプログラマーがパブリックとして使用する必要があるタイプのみを宣言し、パッケージの実装の詳細に属するタイプを非表示にする必要があります。このテクノロジーは私たちに大きな柔軟性を提供し、プログラマーはアクセスできないこれらのタイプの実装の詳細に依存していないため、実装の詳細を変更するときに自由に変更できます。
公共、保護、またはプライベートとして宣言されていないクラスメンバーは、パッケージ内の任意のコードで直接アクセスできますが、パッケージの外側から隠されています。つまり、デフォルトのアクセス修飾子は「パッケージ」であり、インターフェイスのメンバーを除き、デフォルトのアクセス修飾子は「public」です。
パッケージ内でプライベートと宣言されていないフィールドまたはメソッドは、そのパッケージ内の他のすべてのコードからアクセスできるため、同じパッケージのクラスは「フレンドリー」または「信頼できる」と見なされます。これにより、事前定義されたコードとプレースホルダーコードを組み合わせたアプリケーションフレームワークを定義することができます。ここでは、プレースホルダーコードがフレームワーククラスのサブクラスによってオーバーライドされます。事前定義されたコードは、パッケージアクセス修飾子を使用して、パッケージ内の他の共同コードが直接アクセスできるようにしますが、パッケージ外のユーザーの場合、これらのコードはアクセスできません。ただし、これらのコードが配置されているパッケージのサブパッケージは信頼されておらず、その逆も同様です。たとえば、パッケージDITのパッケージアクセス修飾子で変更されたコードは、子パッケージdit.datのコードではアクセスできません。
したがって、各タイプは3つの異なる契約を定義します。
.publi。契約:タイプの主な関数を定義します。
保護された契約:専門化のためにサブクラスが利用できる機能を定義します。
パッケージ契約:パッケージ内の他のコードによって取得できる関数を定義して、パッケージ内のタイプ間のコラボレーションを実現します。これらの契約はすべて、慎重な検討と設計が必要です。
アクセシビリティとカバー方法
スーパークラスでアクセス可能な方法のみをサブクラスに上書きできます。スーパークラスのメソッドにアクセスできない場合、サブクラスのメソッドがメソッドと同じ名前を持っていても、メソッドをサブクラスでオーバーライドすることはできません。ランタイム時にメソッドが呼び出されると、システムはそのアクセシビリティを考慮して、どの実装が実行されているかを決定します。
以下の特別に構築された例をより明確に説明します。 P1パッケージで抽象的なベースクラスを宣言するとします。
パッケージP1; {ab abab public abstract class abstractbase private void pri(){print( "stractbase.pri()"):} void pac(){print( "stractbase.pac()"); } protected void pro(){print( "stractbase.pro()"); } public void pub(){print( "stractbase.pub()");} public final void show()pri(); pac(); pro();パブ(); }}このクラスでは、それぞれ異なるアクセス修飾子を持つ4つのメソッドを定義し、メソッドの本文はそれ自体のみを識別します。このメソッドは、現在のオブジェクト上のこれらの4つのメソッドを順番に呼び出します。この方法をさまざまなサブクラスオブジェクトに適用すると、これらのメソッドのどの実装が呼び出されるかを説明できます。
次に、AbstractBaseクラスを拡張しますが、P2パッケージにあります。
パッケージP2; P1.ABSTRACTBASEパブリッククラスconcreTel拡張abstractBase {public void pri(){print( "concretel.pri()");} public void pac(){concretel.pac() ");} public void pro(){concretel.pro()") ") pub(){print( "concretel.pub()");}}スーパークラスの4つの方法はこのクラスで再宣言され、その実装が変更され、それらがCon-Cretelクラスに属していることを報告しています。同時に、彼らのアクセス権は、他のコードがアクセスするために公開されています。次のコードを実行します
新しいconcretel()。show():
次の出力が生成されます。
abstractbase.pri()abstractbase.pac()concretel.pro()concretel.pub()
プライベートメソッドPRIにサブクラス(または他のクラス)でアクセスできないため、showメソッドは常にAbstractBaseクラスでPRIメソッドの実装を呼び出します。 AbstractBaseクラスのパッケージアクセス権限を備えたPACメソッドは、ConcreTelでアクセスできないため、ConcreTelクラスでPACメソッドの実装はAbstractBaseクラスの定義をオーバーライドできないため、showメソッドはAbstractBase.pacメソッドを呼び出します。 ProメソッドとPUBメソッドはどちらもコンクリーテルクラスでアクセスでき、上書きすることができるため、showメソッドはコンクリーテルクラスでこれら2つのメソッドの実装を呼び出します。
クラスコンクリートを拡張するには、クラスのConcrete2を意味するFoot Meaning Class Concretelに従ってから、AbstractBaseクラスと同じパッケージP1に入れます。
パッケージP1; Import P2.ConcreTel Public Class Concrete2 Extends ConcreTel {public void pri(){print( "concrete2.pri()");} public void pac(){print( "concrete2.pac()") pub(){print( "concrete2.pub()");}}Concretelのメソッドにはパブリックアクセス権があるため、Concrete2でアクセスでき、Concrete2の各方法は対応する方法を個別にカバーします。さらに、Concrete2とAbstractBaseは同じパッケージに含まれているため、メソッドabstractBase.pacにもconcrete2にアクセスでき、メソッドconcrete2.pacはオーバーライドできます。 concrete2オブジェクトのshowメソッドを呼び出すと、印刷の結果は次のとおりです。
abstractbase.pri()concrete2.pac()concrete2.pro()concrete2.pub()
最後に、クラスConcrete3を定義してクラスConcrete2を拡張し、パッケージP3に入れます。
パッケージP3インポートP1.Concrete2;パブリッククラスconcrete3はconcrete2を拡張します{public void pri(){print( "concrete3.pri()");} public void pac q {print( "concrete3.pac()");} print( "concrete3.pro()");} print( "concrete3.pub();concrete3オブジェクトのshowメソッドを呼び出すと、印刷の結果は次のとおりです。
abstractbase.pri()concrete3.pac()concrete3.pro()concrete3.pub()
ここで、メソッドconcrete3.pacはアクセス不可のabstractbase.pacメソッドを無効にしているように見えますが、実際、メソッドconcrete3.pacはメソッドconcrete2.pac、およびメソッドconcrete2.pacをオーバーライドし、メソッドabstractbase.pacをオーバーライドします。クラスConcrete2のPACメソッドをパブリックアクセス権限を持つように再編成することにより、あらゆるサブクラスがアクセスして上書きすることができます。
パッケージオブジェクトと仕様
通常、パッケージはいくつかの仕様を実装し、通常は組織からのものです。パッケージオブジェクトは他の反射タイプとは異なり、パッケージの作成または操作に使用することはできませんが、パッケージ(タイトル、ベンダー、バージョン番号)によって実装された仕様に関する情報とパッケージ自体(タイトル、ベンダー、およびパッケージのバージョン番号)の実装に関する情報を提供する情報を提供するための知識ベースとしてのみ機能します。通常、パッケージは個々の組織からのものですが、実装する仕様(統計分析ライブラリなど)は、他の組織によって定義される場合があります。パッケージを使用するプログラムは、特定のバージョンでのみ定義されている機能を使用できるように、パッケージによって実装された仕様のバージョンを知る必要がある場合があります。同様に、これらのプログラムは、主に異なるバージョンで考えられる欠陥に対処するために、どの実装バージョンが提供されているかを知る必要がある場合があります。パッケージクラスの主な方法のいくつかは、この情報へのアクセスを可能にします。
public public stri ng getName():パッケージの名前を返します。
.public String getSpecificationTitle P:パッケージによって実装された仕様のタイトルを返します。タイトルが不明な場合は、nullを返します。
.public string getSpecificationversion():パッケージによって実装された仕様のバージョン情報を説明する文字列を返します。バージョン情報が不明の場合は、nullを返します。
.public String getSpecificationVendor Q:パッケージによって実装された仕様を所有および維持するサプライヤーの名前を返します。サプライヤーが不明の場合は、nullを返します。
.public string getImplerEntationTitle():パッケージが提供する実装のタイトルを返します。タイトルが不明の場合、null、・public string getimplementationversion()を返します:パッケージが提供する実装のバージョン情報を説明する文字列を返します。バージョン情報が不明の場合、nullを返します。
public Public String getImplementationVendor():実装を提供する組織(ベンダー)の名前を返します。組織が不明の場合は、nullを返します。
たとえば、システム内のjava.langパッケージからこれらの情報を抽出すると、次の結果が得られます。
仕様タイトル:JavaプラットフォームAPI仕様仕様バージョン:1.4仕様ベンダー:Sun Microsystems、Inc。実装タイトル:Javaランタイム環境実装バージョン:1.5.0_02実装ベンダー:Sun Microsystems、Inc。
標準バージョン番号は、「2.0」や'11 .0.12 'などの周期区切り文字によって区切られた非陰性数字で構成されています。このパターンを使用すると、iscompatible withメソッドを呼び出して、このパターンに続くバージョン番号をパッケージのバージョン番号と比較できます。パッケージのバージョン番号が後継者のバージョン番号以上である場合、メソッドはtrueを返します。この比較は、一度に期間分離された数のみを比較します。これらの数値のいずれかが、渡されたバージョン番号の対応する位置よりも小さい場合、2つのバージョンは互換性がありません。バージョン番号の1つが他のバージョン数よりも長い場合、短いバージョン番号の欠落部分はゼロと見なされます。たとえば、パッケージの正規バージョン番号が「1.4」で、「1.2」、「1.3.1」、または「.1.81。」と比較すると、trueが返されます。ただし、「1.4.2 '。または「.5」と比較すると、falseが返されます。この結論は、仕様バージョンが後方互換であると想定しているため、この結論が描かれます。
実装バージョン番号の指定形式はありません。これは、実装を提供するさまざまな組織が実装バージョンを異なる方法で定義するためです。実装バージョン間で行うことができる唯一の比較は、バージョンが同じかどうかをテストすることであり、後方互換性の仮定がない場合です。
パッケージを密封することができます。つまり、クラスをパッケージに追加できなくなります。封印されていないパッケージには、クラスの検索パス内の複数の異なる場所からのクラスを含めることができますが、密閉されたパッケージの内容は、特定のアーカイブまたはURLで指定された場所から同じ場所から来る必要があります。パッケージが密封されているかどうかを判断するには、次の2つの方法があります。
.public boolean issealed p:パッケージが密閉されている場合はtrueoを返します
.Public Boolean Issealed(URL URL):特定のURLに対してパッケージが密閉されている場合、つまりパッケージ内のクラスをこの指定されたURLからロードできます。パッケージのクラスを特定のURLからロードできない場合、またはパッケージが密閉されていない場合、Falseが返され、パッケージの仕様と実装情報は通常、パッケージに保存されているマニフェストファイルの一部として提供されます。パッケージ内のクラスがロードされると、この情報は人によって読まれます。クラスローダーは、ロードするクラスのパッケージオブジェクトを動的に定義できます。
保護されたパッケージDENEPACKAGE(文字列名、文字列スペクトル、文字列導電、文字列仕様、文字列Impltitle、文字列実装、String Implvendor、URL SealBase):このメソッドは、対応するQuoteによって設定された特定のパッケージ名と仕様と実装値を備えたパッケージオブジェクトを返します。パラメーターシールベースがnullの場合、パッケージは密閉されていません。そうしないと、このURL用にパッケージが密閉されています。クラスのパッケージオブジェクトは、クラスを定義する前に定義する必要があり、パッケージ名はクラスローダーで一意でなければなりません。パッケージ名が既存の名前で繰り返されると、作業11EGA1ARGUMENTEXCEPTIONがスローされます。
指定されたクラスのクラスオブジェクトのGetPackageメソッドを呼び出して、このクラスのパッケージオブジェクトを取得できます。また、特定のパッケージ名を使用して静的パッケージを呼び出してパッケージオブジェクトを取得するか、Static Package.getPackagesを呼び出すこともできます。どちらの方法も、コードを呼び出すクラスローダーに関連しています。これらのコードは、クラスローダーのゲットパッケージまたはgetパッケージメソッドを呼び出すためです。これらのクラスローダーのメソッドは、特定のクラスローダーとすべての親クラスローダーを検索し、現在のクラスローダーの設定が行われない場合、現時点ではシステムクラスローダーが使用されます。パッケージが不明の場合、この時点でパッケージ内のタイプがロードされていないため、クラスローダーメソッドがNULLを返すことに注意してください。