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アノテーションは、利用できる最も便利なツールではないかもしれませんが、ここで見たように、特定の状況で使用できます。
いつものように、まれにしか使用しない場合もありますが、開発者ツールボックスで利用できる別のツールは非常に有益です。 このツールが必要になったときは、その仕組みを知っておく価値があります。