Javaの合成クラスとは何ですか? なぜ使用する必要があるのですか?どのように使用できますか?
13 に答える
Java には、実行時にクラスを作成する機能があります。これらのクラスは、合成クラスまたは動的プロキシとして知られています。
詳細については、 http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.htmlを参照してください。
CGLIBやASMなどの他のオープンソース ライブラリでも合成クラスを生成でき、JRE で提供されるライブラリよりも強力です。
合成クラスは、Spring AOP や AspectJ などの AOP (アスペクト指向プログラミング) ライブラリや、Hibernate などの ORM ライブラリで使用されます。
さて、Googleで最初の質問に対する答えを見つけました:
クラスがコンパイラによって生成された場合、つまり、ソース コードに表示されない場合、そのクラスは合成としてマークされることがあります。
これは単なる基本的な定義ですが、フォーラムのスレッドで見つけましたが、説明はありませんでした。まだまだ良い方を探して…
たとえば、switch ステートメントがある場合、Java は $ で始まる変数を作成します。この例を見たい場合は、switch ステートメントを含むクラスの Java リフレクションをのぞいてみてください。これらの変数は、クラス内の任意の場所に少なくとも 1 つの switch ステートメントがある場合に表示されます。
あなたの質問に答えるために、合成クラスに(リフレクション以外で)アクセスできるとは思いません。
(リフレクションを介して) 何も知らないクラスを分析していて、そのクラスに関する非常に具体的で低レベルのことを知る必要がある場合、合成クラスに関係する Java リフレクション メソッドを使用することになる可能性があります。ここでの唯一の「使用」は、コードで適切に使用するために、クラスに関する詳細情報を取得することです。
(これを行っている場合は、他の開発者が使用できる何らかのフレームワークを構築している可能性があります。)
それ以外の場合、リフレクションを使用していない場合、私が知っている合成クラスの実用的な使用法はありません。
合成クラス/メソッド/フィールド:
これらは VM にとって重要です。次のコード スニペットをご覧ください。
class MyOuter {
private MyInner inner;
void createInner() {
// The Compiler has to create a synthetic method
// to construct a new MyInner because the constructor
// is private.
// --> synthetic "constructor" method
inner = new MyInner();
// The Compiler has to create a synthetic method
// to doSomething on MyInner object because this
// method is private.
// --> synthetic "doSomething" method
inner.doSomething();
}
private class MyInner {
// the inner class holds a syntetic ref_pointer to
// the outer "parent" class
// --> synthetic field
private MyInner() {
}
private void doSomething() {
}
}
}
このディスカッションによると、言語仕様ではクラスの「isSynthetic」プロパティが記述されていますが、これは実装によってほとんど無視され、動的プロキシまたは匿名クラスには使用されません。合成フィールドとコンストラクターは、ネストされたクラスを実装するために使用されます (ネストされたクラスの概念は、バイト コードにはなく、ソース コードにのみ存在します)。
合成クラスの概念は役に立たないことが証明されただけだと思います。つまり、クラスが合成かどうかは誰も気にしません。フィールドとメソッドでは、おそらく 1 つの場所で使用されます: IDE クラス構造ビューに何を表示するかを決定するため - 通常のメソッドとフィールドはそこに表示されますが、ネストされたクラスをシミュレートするために使用される合成のものは表示されません。OTOH、匿名クラスをそこに表示する必要があります。
これらは、デバッグ目的で内部クラスのプライベート メンバーを呼び出すときに、実行時に JVM によって作成されます。
実行目的で実行時に JVM によって作成されるメソッド、フィールド、クラスは、Synthetic と呼ばれます。
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
また、シンセティック クラスまたは動的プロキシは、実行時にインターフェースまたは抽象クラスの実装を作成するために EasyMock によって使用されます。
Java コンパイラは、内部クラスなどの特定の構造をコンパイルするときに、合成構造を作成します。これらは、ソース コードに対応する構造を持たないクラス、メソッド、フィールド、およびその他の構造です。
用途:
合成構造により、Java コンパイラーは、JVM を変更することなく、新しい Java 言語機能を実装できます。ただし、合成コンストラクトは Java コンパイラの実装ごとに異なる場合があります。つまり、.class ファイルも実装ごとに異なる可能性があります。
参照: docs.oracle.com
正しく理解すれば、合成クラスはその場で生成されるクラスであり、明示的な名前を付ける必要はありません。例えば:
//...
Thread myThread = new Thread() {
public void run() {
// do something ...
}
};
myThread.start();
//...
これにより、Thread の合成サブクラスが作成され、その run() メソッドがオーバーライドされ、インスタンス化されて開始されます。
合成クラスはコードには表示されません。コンパイラによって作成されます。たとえば、java のコンパイラによって作成されるブリッジ メソッドは、通常、合成です。
public class Pair<T> {
private T first;
private T second;
public void setSecond(T newValue) {
second = newValue;
}
}
public class DateInterval extends Pair<String> {
public void setSecond(String second) {
System.out.println("OK sub");
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
DateInterval interval = new DateInterval();
Pair pair = interval;
pair.setSecond("string1");
}
}
コマンドを使用するとjavap -verbose DateInterval
、ブリッジ メソッドを確認できます。
public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
これはコンパイラによって作成されました。コードには表示されません。