1. 序章

KotlinはJVMのプログラミング言語であり、Javaバイトコードに直接コンパイルされます。 ただし、Javaよりもはるかに簡潔であり、特定のJVM機能は言語に直接適合しません。

代わりに、 Kotlinは、これらの機能をトリガーするためにコードに適用できる一連のアノテーションを提供します。 これらはすべて、kotlin-stdlib内のkotlin.jvmパッケージに含まれています。

これらの中で最も難解なものの1つは、@JvmSyntheticアノテーションです。

2. @JvmSynthetic は何をしますか?

このアノテーションは、メソッド、フィールド、ゲッター、およびセッターに適用できます。は、生成されたクラスファイルで適切な要素を合成としてマークします。

このアノテーションは、他のアノテーションとまったく同じようにコードで使用できます。

@JvmSynthetic
val syntheticField: String = "Field"

var syntheticAccessor: String
  @JvmSynthetic
  get() = "Accessor"
  
  @JvmSynthetic
  set(value) {
  }

@JvmSynthetic
fun syntheticMethod() {
}

上記のコードがコンパイルされると、コンパイラはACC_SYNTHETIC属性をクラスファイルの対応する要素に割り当てます。

private final java.lang.String syntheticField;
  descriptor: Ljava/lang/String;
  flags: ACC_PRIVATE, ACC_FINAL, ACC_SYNTHETIC
  ConstantValue: String Field
  RuntimeInvisibleAnnotations:
    0: #9()

public final void syntheticMethod();
  descriptor: ()V
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SYNTHETIC
  Code:
    stack=0, locals=1, args_size=1
       0: return
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       1     0  this   Lcom/baeldung/kotlin/SyntheticTest;
    LineNumberTable:
      line 20: 0

3. 合成属性とは何ですか?

ACC_SYNTHETIC属性は、要素が元のソースコードに実際には存在せず、代わりにコンパイラによって生成されたことを示すために、JVMバイトコードによって意図されています。

当初の目的は、Java 1.1でネストされたクラスとインターフェースをサポートすることでしたが、今では、必要になる可能性のある任意の要素に適用できます。

コンパイラが合成としてマークする要素は、Java言語からアクセスできなくなります。 これには、IDEなどのツールに表示されないことも含まれます。 ただし、Kotlinコードにはそのような制限はなく、これらの要素を完全に表示してアクセスできます。

@JvmSynthetic で注釈が付けられているが、 @JvmField、で注釈が付けられていないKotlinフィールドがある場合、生成されたゲッターとセッターは合成メソッドとは見なされず、問題なくアクセスできます。

合成要素を見つけることができれば、Reflection APIを使用してJavaから合成要素にアクセスできます(たとえば、名前で)。

Method syntheticMethod = SyntheticClass.class.getMethod("syntheticMethod");
syntheticMethod.invoke(syntheticClass);

4. これは何に使用できますか?

これの唯一の本当の利点は、Java開発者とツールからコードを隠すことと、コードの状態に関する他の開発者への指標としてです。 これは、最も一般的なアプリケーションコードよりもはるかに低いレベルで動作することを目的としています。

コード生成をサポートし、コンパイラが他の開発者に公開されるべきではないが、実際に公開されたインターフェイスをサポートするために必要なフィールドとメソッドを生成できるようにすることを目的としています。 これは、プライベートまたは内部を超える保護レベルと考えることができます。

または、コードカバレッジや静的分析などの他のツールからコードを非表示にするために使用することもできます。

ただし、特定のツールがこのフラグを尊重するという保証はないため、ここで常に役立つとは限りません。

5. 結論

@JvmSynthetic アノテーションは、利用可能な最も便利なツールではないかもしれませんが、ここで見たように、特定の状況で使用できます。

いつものように、私たちがそれを使用することはめったにないかもしれませんが、開発者ツールボックスで利用可能な別のツールは非常に有益です。 このツールが必要になったときは、それがどのように機能するかを知る価値があります。