10

jarファイルで一部のクラスを非表示にすることは本当に不可能ですか?

クラスをより柔軟に保つために、クラスの直接インスタンス化を許可したくありませんでした。この jar のファクトリ (またはファサード) のみが表示されます。

2 つのプロジェクトを作成する以外に、この問題を解決する方法はありますか? (2 つのプロジェクト: 最初のプロジェクトにはクラス (実装) が含まれ、もう 1 つのプロジェクトには最初のプロジェクトへの参照とファクトリが含まれます。後で 2 番目のプロジェクトのみが参照されます)

4

8 に答える 8

5

実際のクラスを非表示にするつもりはないことを理解しています。ファクトリ クラスの外での構築を防止するだけです。これは、クラス コンストラクターでパッケージ プライベート (デフォルト) の可視性を使用することで、非常に簡単に実現できると思います。唯一の制限は、クラスとファクトリを同じパッケージに含める必要があることです。そのため、中規模から大規模なコードベースでは、必要以上に複雑になる可能性があります。

于 2011-01-21T14:19:30.557 に答える
4

あなたの質問を正しく理解できれば、ライブラリのユーザーが、コンストラクター自体を使用するのではなく、ファクトリを使用してオブジェクトをインスタンス化することを強制されることを確認したいと思います。

私が見る限り、2 つの可能性があります。1 つはばかげていますが、いくつかの特定のケースで使用できます。もう 1 つは、最も実用的で、おそらく最も一般的に使用される方法です。

  1. すべてのクラスをファクトリのプライベート内部クラスにすることができます 。これは、クラスごとに 1 つのファクトリがある場合は機能しますが、1 つのファクトリで管理されているさまざまなクラスが多数ある場合はほとんど機能しません。
  2. protectedアクセス修飾子を使用して、クラス コンストラクターへのアクセスを制限できます。これは、ファクトリ パターンを使用する場合の一般的な方法です。
于 2011-01-21T14:19:40.447 に答える
3

パブリックファクトリメソッドが「隠された」ものを返そうとすると、コンパイラの失敗または警告が発生すると思います。

ClassLoaderいいえ、独自のクラスを再実装するか、OSGi などを使用しない限り、public クラスを非表示にすることはできません。

あなたができることは、インターフェースAPIを実装から分離することです。たとえば、インターフェースのみを含む1つのプロジェクトと、実装を含む別のプロジェクトを作成します。ただし、実装クラスを非表示にすることはできません。

于 2011-01-21T14:20:44.247 に答える
2

標準のクラスローダーと単純な古い jar ファイルでは、これは不可能です。OSGi には、一部のパッケージのみを別のバンドルに可視化するというこの概念があります (つまり、公開 API と内部実装の分離)。

Eclipse を使用している場合は、これを使用してそのようなルールを適用できます

于 2011-01-21T14:09:39.360 に答える
2

難読化は何らかの形で役に立ちます。

于 2011-01-21T14:07:33.363 に答える
1

あなたの質問には、すべてのクラスを同じパッケージに保持する必要のない 2 つの解決策があります。

1 つ目は、(Practical API Design、Tulach 2008) で説明されている Friend Accessor/ Friend Packageパターンを使用することです。

2 つ目は、OSGi を使用することです。OSGi がこれをどのように達成するかを説明する 記事がここにあります。

関連する質問: 123、および4

于 2011-05-27T15:41:55.697 に答える
1

「クラスをより柔軟に保つためにクラスの直接インスタンス化を許可しない」と言うとき、私があなたを正しく理解していれば、適切に実行されたファサードパターンがこれを処理します。

非表示にするすべてのクラスのコンストラクターをパッケージ スコープに制限します。ファサード クラスをパブリック スコープに開きます。

http://mindprod.com/jgloss/packagescope.html

「クラスのクライアントに直接アクセスさせたくない変数またはメソッドがクラスにある場合は、それに public、protected、または private 宣言を与えないでください。Java の設計上の見落としにより、できます」デフォルトの「パッケージ」アクセシビリティを明示的に宣言しない. パッケージの他のメンバーはそれを見ることができますが, あなたのものから継承するパッケージ外のクラスは見えません.同じパッケージの一部でなくても、クラスを継承します。パッケージ スコープ (デフォルト) メソッドはそうではありません。それが、保護されたスコープとパッケージ スコープの唯一の違いです。"

于 2011-01-21T14:19:49.560 に答える
0

カスタムクラスローダーでそのような魔法を行うことができますが:

  • 正しい分離は、クラス ローダーを配置したプロジェクトでのみ利用できます。
  • そのようなローダーを作成する努力が価値があるかどうかは、本当に疑わしいです。

そのような状況では、標準の Java で見られるものと同様のことを行います。Egyou see javax.xml.stream.XMLInputFactorybut どこかにありますcom.sun.xml.internal.stream.XMLInputFactoryImpl。次のように記述すれば、完全にコンパイル可能です。

new com.sun.xml.internal.stream.XMLInputFactoryImpl()

あなたはほとんどそれをしませんが:-)システムプロパティを使用すると、ロードされている実際の実装を制御できます。私にとって、そのようなアプローチは多くの状況で問題ありません。

あなたの質問を正しく理解できたと思います;)

乾杯!

于 2011-01-21T14:19:55.473 に答える