Kotlinの@JvmSyntheticアノテーション

Kotlinの@JvmSyntheticアノテーション

1. 前書き

Kotlin is a programming language for the JVM and compiles directly to Java Bytecode。 ただし、Javaよりもはるかに簡潔であり、特定のJVM機能は言語に直接適合しません。

代わりに、Kotlin provides a set of annotations that we can apply to our code to trigger these features。 これらはすべて、kotlin-stdlib内のkotlin.jvmパッケージに存在します。

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

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

このアノテーションは、メソッド、フィールド、ゲッター、およびセッターに適用できます—そしてそれはmarks the appropriate element as synthetic in the generated class file.です

この注釈は、他の注釈とまったく同じようにコードで使用できます。

@JvmSynthetic
val syntheticField: String = "Field"

var syntheticAccessor: String
  @JvmSynthetic
  get() = "Accessor"

  @JvmSynthetic
  set(value) {
  }

@JvmSynthetic
fun syntheticMethod() {
}

上記のコードをコンパイルすると、the compiler assigns the ACC_SYNTHETIC attribute to the corresponding elements in the class file

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/example/kotlin/SyntheticTest;
    LineNumberTable:
      line 20: 0

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

The ACC_SYNTHETIC attribute is intended by the JVM Bytecode to indicate that an element wasn’t actually present in the original source codeですが、代わりにコンパイラによって生成されました。

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

Any element that the compiler marks as synthetic will be inaccessible from the Java language。 これには、IDEなどのツールで表示されないことも含まれます。 ただし、Kotlinコードにはそのような制限はなく、これらの要素を完全に表示およびアクセスできます。

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

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

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

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

これの唯一の本当の利点は、Java開発者とツールからコードを隠すことと、コードの状態に関して他の開発者に示すことです。 It’s intended for working at a much lower level than most typical application code

The intention of it is to support code generation。コンパイラーが、他の開発者に公開されるべきではないが、実際に公開されたインターフェースをサポートするために必要なフィールドとメソッドを生成できるようにします。 これは、privateまたはinternalを超える保護レベルと考えることができます。

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

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

5. 結論

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

いつものように、まれにしか使用しない場合もありますが、開発者ツールボックスで利用できる別のツールは非常に有益です。 このツールが必要になったときは、その仕組みを知っておく価値があります。