2016-12-07 7 views
15

私はkotlin-stdlibの@JvmSynthetic注釈を見つけました。それは何のためか不思議ですが、残念ながら、それは文書化されていません。Kotlinの@JvmSyntheticの使用目的は何ですか?

私が理解する限り、それをプログラム要素に適用すると、synthetic修飾子が対応するバイトコード要素に追加されます。その結果、要素は、Javaから見えなくなる:

どこかJavaコードで
class MyClass { 
    @JvmSynthetic 
    fun f() { } 
} 

MyClass c = new MyClass(); 
c.f() // Error: cannot resolve method f() 

しかし、同じ要素にはKotlinコードではまだ表示されている:

val c = MyClass() 
c.f() // OK 

が隠れています非Kotlinソースからの宣言は@JvmSyntheticの有効な使用ですか?それは意図された使用ですか?他の適切なユースケースは何ですか?

@JvmSyntheticはJavaの機能を隠すので、Javaでも無効にすることはできません(また、abstractのメンバーになると、呼び出しはAbstractMethodErrorになります)。それで、@JvmSyntheticを使って、JavaソースでKotlinクラスのメンバーを上書きすることを禁止できますか?

答えて

9

プレーンJavaでは、syntheticのメソッドがjavacコンパイラによって生成されます。通常、プライベート修飾子で指定されたフィールドに囲まれたクラスがアクセスするとき、コンパイラはネストされたクラスに対して合成メソッドを作成する必要があります。

Javaでは以下のクラスを考える:

public final class SyntheticSample 
{ 
    public static void main(final String[] args) 
    { 
     SyntheticSample.Nested nested = new SyntheticSample.Nested(); 
     out.println("String: " + nested.syntheticString); 
    } 

    private static final class Nested 
    { 
     private String syntheticString = "I'll become a method!"; 
    } 
} 

SyntheticSampleクラスがnested.syntheticStringフィールドにアクセスするとき、それは確かに(access$100のようなものを命名)、コンパイラによって生成された静的syntheticメソッドを呼び出しています。

Kotlinが合成メソッドの作成を強制することができる@JvmSynthetic注釈を公開しても、通常の「ユーザー」コードでは使用しないことをお勧めします。合成メソッドは、コンパイラによって作成された低レベルのトリックであり、日常的なコードではこうしたものに決して頼るべきではありません。私はそれが標準ライブラリの他の部分をサポートするためのものだと思っていますが、好奇心が強い場合は直接JetBrainsの人に尋ねてください(Kotlin Discussion Forumを試してください)

+1

慎重に扱う必要がある危険なツールのようです、まだそれは 'kotlin-stdlib'の一部ですが、それは公開APIです。通常の開発者(あるいはライブラリ/ツール開発者)が遭遇する可能性のある '@ JvmSynthetic'の使用例があるはずです。また、 '合成'メソッドは 'javac'によって幅広く使用され、ネストされたクラスに対してのみ使用されます。少なくとも、別のシグネチャを持つメソッドをオーバーライドするには(非ジェネリックメソッドでオーバーライドされたジェネリックメソッドを含む)。 – hotkey

関連する問題