JARファイルにクラスを隠す
-
16-10-2019 - |
質問
JARファイルにいくつかのクラスを非表示にすることは本当に不可能ですか?
クラスの直接インスタンス化を許可して、より柔軟に保つことを許可したくありませんでした。工場(またはファサード)のみがこの瓶を見る必要があります。
2つのプロジェクトを作成する以外に、この問題を解決する以外の方法はありますか? (2つのプロジェクト:最初のプロジェクトにはクラス(実装)が含まれ、もう1つは最初のプロジェクトを参照し、工場を含みます。後で2番目のプロジェクトのみが参照されます)
解決
パブリックファクトリーの方法が「隠されている」何かを返そうとする場合、コンパイラの失敗または警告があると思います。
いいえ、自分のクラスを再実装せずに公開クラスを隠すことはできません ClassLoader
またはOSGIまたは同様のものを使用します。
できることは、インターフェイスAPIを実装から分離することです。たとえば、インターフェイスのみを含む1つのプロジェクトと、デプレンスを含む別のプロジェクトがあります。ただし、実装クラスを非表示にすることはできません。
他のヒント
私はあなたが実際のクラスを隠そうとしていないことを理解しており、工場のクラスの外で彼らの建設を防ぐだけです。これは、クラスコンストラクターでパッケージプライベート(デフォルト)の可視性を使用することで非常に簡単に実現できると思います。唯一の制限は、同じパッケージにクラスと工場を用意する必要があるため、中程度から大規模なコードベースでは不必要に複雑になる可能性があることです。
私があなたの質問を正しく理解している場合、あなたはあなたのライブラリのユーザーがあなたの工場を使用して、コンストラクター自身を使用するのではなく、オブジェクトをインスタンス化することを強制されることを確認したいと思います。
私が見るように、2つの可能性がありますが、そのうちの1つは愚かですが、少数の特定のケースで使用可能であり、もう1つは最も実用的で、おそらく最も一般的に使用される方法です。
- すべてのクラスを作成できますプライベートインナークラス 工場の。これは、クラスごとに1つの工場がある場合に機能しますが、1つの工場で多くの異なるクラスが管理されている場合、ほとんど実行できません。
- 使用できます
protected
アクセス修飾子は、クラスコンストラクターへのアクセスを制限します。 これは一般的な慣行です を使用する場合 工場パターン.
難読化 あなたを助けられる 何とかして.
標準のクラスローダーでは、プレーンな古いJARファイルでは、これは不可能です。 OSGIは、他のバンドルに見えるようにするこの概念を、他のパッケージのみであり、他のパッケージではなく(つまり、パブリックAPIと内部実装の分離)。
あなたがusinf Eclipseである場合、あなたはそのようなルールを実施することができます これ
「クラスの直接インスタンス化を許可して柔軟性を高めないようにしないでください」と言ったときに正しく理解した場合、適切に実行されたファサードパターンがこれを処理します。
隠したいすべてのクラスのコンストラクターをパッケージスコープに制限します。ファサードクラスを公開範囲から開きます。
http://mindprod.com/jgloss/packagescope.html
「クラスに直接アクセスしたくない変数や方法がある場合は、公開、保護された、または私的宣言を与えないでください。Javaの設計が監視されているため、できます。 tデフォルトの「パッケージ」アクセシビリティを明示的に宣言します。パッケージの他のメンバーはそれを見ることができますが、あなたから継承するパッケージの外側のクラスはそうではありません。保護されたアクセシビリティ属性はわずかに視覚的に提供されます。同じパッケージの一部ではないクラスを継承するために。パッケージスコープ(デフォルト)メソッドはそうではありません。それが保護された範囲とパッケージスコープの唯一の違いです。」
カスタムクラスローダーでこのような魔法を行うことができますが、
- 正しい分離は、クラスローダーのスタッフが配置されたプロジェクトでのみ利用可能になります。
- そのようなローダーを作成する努力が価値があることは本当に疑わしいです。
そのような状況では、私は標準のJavaで見るかもしれないものに似たことをします。 egyouは参照してください javax.xml.stream.XMLInputFactory
しかし、どこかにあります com.sun.xml.internal.stream.XMLInputFactoryImpl
. 。あなたが書くならば、それは完全に編集可能です:
new com.sun.xml.internal.stream.XMLInputFactoryImpl()
あなたはほとんどそれをしません:-)システムプロパティを使用すると、ロードされている実際の実装を制御できます。私にとって、そのようなアプローチは多くの状況で問題ありません。
私はあなたの質問を正しく理解したことを願っています;)
乾杯!