コトリン注釈

1. 概要

このチュートリアルでは、Kotlinアノテーションの概要を説明します。
それらを適用する方法、独自のものを作成およびカスタマイズする方法を示します。 次に、JavaとKotlinのアノテーションとキーワードの相互作用について簡単に説明します。
最後に、注釈を処理する方法を示すクラス検証の簡単な例を示します。

2. 注釈を適用する

Kotlinでは、コード要素の前に@記号をプレフィックスとして付けた名前を付けることにより、注釈を適用します。 たとえば、_Positive_という名前の注釈を適用する場合、次のように記述する必要があります。
@Positive val amount: Float
多くの場合、注釈にはパラメーターがあります。 *注釈パラメータはコンパイル時の定数であり、次のタイプである必要があります*
  • Kotlinプリミティブ型(Int、Byte、Short、Float、Double、Char、
    ブール

  • 列挙

  • クラス参照

  • 注釈

  • 上記のタイプの配列

    注釈にパラメーターが必要な場合、関数呼び出しのように括弧でその値を提供します。
@SinceKotlin(version="1.3")
この場合、注釈パラメーターも注釈である場合、@ symbol __:__を省略する必要があります
@Deprecated(message="Use rem(other) instead", replaceWith=ReplaceWith("rem(other)"))
注釈パラメーターがクラスオブジェクトである場合、クラス名に_

class_を追加する必要があります。次に例を示します。

@Throws(IOException::class)
注釈パラメーターに複数の値を設定できるように指定する必要がある場合は、それらの値の配列を渡すだけです。
@Throws(exceptionClasses=arrayOf(IOException::class, IllegalArgumentException::class))
Kotlin 1.2以降では、次の構文も使用できます。
@Throws(exceptionClasses=[IOException::class, IllegalArgumentException::class])

3. アノテーションを宣言する

注釈を宣言するために、クラスを定義し、__class __oneの前に_annotation_キーワードを配置します。 その性質上、*注釈の宣言にコードを含めることはできません*。
最も単純な注釈にはパラメーターがありません。
annotation class Positive
パラメーターを必要とする注釈の宣言は、プライマリコンストラクターを持つクラスのようなものです。
annotation class Prefix(val prefix: String)
カスタムアノテーションを宣言するとき、どのコード要素に適用するか、どこに保存するかを指定する必要があります。 このメタ情報を定義するために使用される注釈は、_meta-annotations._と呼ばれます。
次のセクションでは、それらについて簡単に説明します。 最新の情報については、https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/index.html [公式ドキュメント]をいつでも確認できます。

3.1. @ターゲット

このメタ注釈は、この注釈が参照できるコード要素を指定します。 * It_AnnotationTarget_列挙のインスタンスまたはその配列である必要がある必須パラメーターがあります*。 したがって、注釈を次の要素に適用することを指定できます。
  • クラス

  • ANNOTATION_CLASS

  • TYPE_PARAMETER

  • PROPERTY

  • フィールド

  • LOCAL_VARIABLE

  • VALUE_PARAMETER

  • コンストラクタ

  • 関数

  • PROPERTY_GETTER

  • PROPERTY_SETTER

  • タイプ

  • EXPRESSION

  • ファイル

  • TYPEALIAS

    明示的に指定しない場合、対応する注釈はデフォルトで次の要素に適用できます。
    _CLASS、PROPERTY、FIELD、LOCAL_VARIABLE、VALUE_PARAMETER、CONSTRUCTOR、FUNCTION、PROPERTY_GETTER、PROPERTY_SETTER_

3.2. @保持

このメタ注釈は、注釈を_.class_ファイルに保存するかどうか、およびリフレクションで表示する必要があるかどうかを指定します。 *必須パラメーターは、次の要素を持つ_AnnotationRetention_列挙のインスタンスである必要があります:
  • ソース

  • バイナリ

  • ランタイム

    Javaとは異なり、Kotlinの_ @ Retention_のデフォルト値は_RUNTIME_です。

3.3. _ @ Repeatable_

_ @ Repeatable_は、要素に同じタイプの複数の注釈があるかどうかを指定します。 このメタ注釈はパラメーターを受け入れません。

3.4. _ @ MustBeDocumented_

_ @ MustBeDocumented_は、生成されたドキュメントに注釈のドキュメントを含めるかどうかを指定します。 このメタ注釈は、パラメータも受け入れません。

4. アノテーションとJavaの相互運用性

通常、KotlinはJavaに関してより簡潔です。 たとえば、プロパティを宣言するときなど、追加のメソッドを自動的に作成します。
val name: String?;
コンパイラは、このプロパティのプライベートフィールドとゲッターとセッターを自動的に作成します。 その結果、疑問が生じます。プロパティに注釈を追加すると、それがどこに適用されるのでしょうか? ゲッター、セッター、またはフィールド自体に?
  • Kotlinでは、Javaコードで定義された注釈でプロパティを修飾すると、対応するフィールドに適用されます。*

    JUnitの_https://junit.org/junit4/javadoc/4.12/org/junit/Rule.html [@Rule] _アノテーションなど、アノテーションがフィールドをパブリックにする必要がある場合、問題に直面する可能性があります。 あいまいさを避けるために、Kotlinにはいわゆるuse-site target宣言があります。

4.1. 使用場所のターゲット宣言

use-siteターゲットはオプションです。 コロン記号を区切り文字として使用して、_ @ _シンボルと注釈名の間に配置します。 この構文により、複数の注釈名を一度に指定できます。
link:/uploads/use-site-target-annotation-both-100x17.png%20100w []
Kotlinフィールドに_ @ get:Positive_を配置する場合、アノテーションは実際にそのフィールドに対して生成されたゲッターをターゲットにする必要があることを意味します。
Kotlinは、以下に対応するuse-siteターゲットの次の値をサポートしています。
  • delegate –委任されたプロパティを格納するフィールド

  • field –プロパティ用に生成されたフィールド

  • file –定義された最上位の関数とプロパティを含むクラス
    そのファイルに

  • get / set –プロパティのゲッター/セッター

  • param –コンストラクターパラメーター

  • property – Kotlinのプロパティ。Javaからアクセスできません
    code

  • receiver –拡張関数の受信側パラメーターまたは
    財産

4.2. JVM関連の注釈

次のKotlin注釈により、Javaコードからの使用方法をカスタマイズできます。
  • _ @ JvmName_ –生成されたJavaメソッドの名前の変更を許可します
    またはフィールド

  • _ @ JvmStatic_ –生成されたJavaメソッドまたは
    フィールドは静的である必要があります

  • _ @ JvmOverloads_ – Kotlinコンパイラーが生成する必要があることを示します
    デフォルトのパラメータを置き換えるオーバーロード関数

  • _ @ JvmField_ –生成されたJavaフィールドがパブリックであることを示します
    ゲッター/セッターのないもの

    一部のJavaアノテーションはKotlinのキーワードになり、その逆も同様です。
Java Kotlin

@Override

override

volatile

@Volatile

strictfp

@Strictfp

synchronized

@synchronized

transient

@Transient

throws

@Throws

5. 注釈の処理

注釈を処理する方法を示すために、簡単なバリデーターを作成しましょう。 ここでは、完全なコードがGithubのhttps://github.com/eugenp/tutorials/tree/master/core-kotlin-2[repository]で入手できる間、アイデアのみを提示します。
an __Item ___のインスタンスが有効かどうかを判断する必要があるとします。
class Item(val amount: Float, val name: String)
_amount_の値が正で、_name_の値が_Alice_または_Bob_の場合、_Item_インスタンスは有効であると想定します。
このために、_Item_クラスのプロパティをカスタムアノテーション_Positive_および_AllowedNames_で装飾しましょう。
class Item(
  @Positive val amount: Float,
  @AllowedNames(["Alice", "Bob"]) val name: String)
単純な実装では、_Item_’sプロパティを取得します。
val fields = item::class.java.declaredFields
for (field in fields) {...}
そして、各プロパティのすべての注釈を反復処理します。
for (annotation in field.annotations) {...}
_Item_’sプロパティを装飾したものを見つけるために。
たとえば、次のコマンドを使用して、プロパティに_AllowedNames_が存在するかどうかを検出できます。
field.isAnnotationPresent(AllowedNames::class.java)
注釈が存在する場合、許可された値と比較するだけで、プロパティに有効な値があるかどうかを簡単に判断できます。
val allowedNames = field.getAnnotation(AllowedNames::class.java)?.names
*注釈ではlink:/java-reflection[the Java Reflection API] *を使用することに注意してください。 その結果、注釈に大きく依存すると、コードのパフォーマンスが低下する可能性があります。

6. 結論

この記事では、Kotlinアノテーションとそれに対応するJavaアノテーションを検討しました。 Kotlinアノテーションを適用する方法、カスタムアノテーションを作成する方法、それらを処理する方法について説明しました。
ご覧のとおり、KotlinアノテーションはJavaのアノテーションと非常によく似ています。 それでも、チュートリアルlink:/java-custom-annotation[Javaでのカスタムアノテーションの作成]も役立つことがあります。
いつものように、完全なコードはhttps://github.com/eugenp/tutorials/tree/master/core-kotlin-2[GitHubリポジトリ]から入手できます。