Kotlinの注釈

KotlinのアノテーションはJavaアノテーションと100%互換性があります。多くの類似点がありますが、いくつかの違いもあります。

1.注釈の性質

注釈は実際には一種のコードラベルであり、注釈が作用するオブジェクトはコードです。特定の注釈コードにいくつかの追加情報を注釈することができます。ただし、これらの情報は、ソースコード期間、コンパイル期間、実行期間など、さまざまな期間で保持できます。その後、さまざまな時点で、実際のコードロジックを処理するために、何らかの方法でラベル情報を取得できます。この方法は、多くの場合、リフレクションと呼ばれます。

2.注釈の定義

KotlinのアノテーションのコアコンセプトはJavaのコンセプトと同じです。アノテーションは、コードにメタデータを提供するために使用されます。また、注釈はコードの実行に直接影響しません。アノテーションを使用すると、追加のメタデータをステートメントに関連付けることができ、メタデータに何らかの方法でアクセスできます(ランタイムリフレクションや一部のソースコードツールなど)。

3.注釈付きステートメント

Kotlinでの宣言とアノテーションの方法はJavaとは少し異なります。Javaでは主に@interfaceキーワードで宣言されますが、Kotlinではアノテーションクラスで宣言するだけで済みます。コンパイラでは禁止されていることに注意してください。 Kotlinではアノテーションクラスはクラス本体を指定します。Kotlinではアノテーションは関連する宣言と式のメタデータの構造を定義するためにのみ使用されるためです。

  • Kotlinアノテーション宣言
package com.fate.annotation
//和一般的声明很类似,只是在class前面加上了annotation修饰符
annotation class TestAnnotation(val value: String)
  • Javaアノテーション宣言
package com.fate.annotation;
//java中的注解通过@interface关键字进行定义,它和接口声明类似,只不过在前面多加@
public @interface TestAnnotation {
    String value();
}

4.注釈の適用

前のステップでは、タグを宣言して定義する方法を知っています。次のステップは、このタグを使用することです。定義したタグを指定したコードに貼り付ける方法です。Kotlinでのアノテーションの使用は、Javaの場合と同じです。適用されるアノテーションは@annotatedクラス名です

@Target(AnnotationTarget.FUNCTION)
@Retention(value = AnnotationRetention.RUNTIME)
annotation class TestAnnotation(val value: Int)//和一般的声明很类似,只是在class前面加上了annotation修饰符

class Test {
    @TestAnnotation(value = 1000)
    fun test() {//给test函数贴上TestAnnotation标签(添加TestAnnotation注解)
        //...
    }
}

アノテーションは、最も一般的なJUnitユニットテストフレームワークなど、多くの一般的なJavaまたはKotlinフレームワークで広く使用されています。

class ExampleUnitTest {
    @Test //@Test注解就是为了告诉JUnit框架,这是一个测试方法,当做测试调用。
    fun addition_isCorrect() {
        assertEquals(4, 2 + 2)
    }
}

で Kotlinクラスの注釈も引数としてクラスを注釈を付けていることができ、Kotlinを見たいかもしれ @Deprecatedこのソースノートだけでなく、その使用を定義します。@Deprecated アノテーションは、元のJavaFoundationのReplaceWith 関数を 拡張します。古いAPIを直接使用でき ます。コンパイラはReplaceWithの新しいAPIに従って新しいAPIを自動的に置き換えることができ ます。これはJavaでは不可能です。クリックしてこのAPIを入力するだけで、新しいAPIを正しく使用するためのソースコードを表示できます。

//@Deprecated注解比Java多了ReplaceWith功能, 这样当你在调用remove方法,编译器会报错。使用代码提示会自动IntelliJ IDEA不仅会提示使用哪个函数提示替代它,而且会快速自动修正。
@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"), level = DeprecationLevel.ERROR)//定义的级别是ERROR级别的,这样当你在调用remove方法,编译器会报错。
@kotlin.internal.InlineOnly
public inline fun <T> MutableList<T>.remove(index: Int): T = removeAt(index)

@非推奨の注釈付き削除関数の使用

//Deprecated注解的使用
fun main(args: Array<String>) {
    val list = mutableListOf("a", "b", "c", "d", "e")
    list.remove(3)//这里会报错, 通过remove函数注解定义,这个remove函数在定义的level是ERROR级别的,所以编译器直接抛错
}

最後に、@ Deprecatedアノテーションの定義を見てみましょう。

@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS)
@MustBeDocumented
public annotation class Deprecated(
        val message: String,
        val replaceWith: ReplaceWith = ReplaceWith(""),//注解类中构造器可以使用注解类作为函数参数
        val level: DeprecationLevel = DeprecationLevel.WARNING
)
@Target()
@Retention(BINARY)
@MustBeDocumented
public annotation class ReplaceWith(val expression: String, vararg val imports: String)

:アノテーションクラスは、次のタイプのパラメータのみを持つことができます:基本データ型、文字列、列挙、クラス参照タイプ、およびその他のアノテーションクラス(たとえば、非推奨のアノテーションクラスのReplaceWithアノテーションクラス)

5.Kotlinのメタアノテーション

KotlinのJavaと同様に、  Kotlinアノテーションクラス自体にもアノテーションを付けることができ、アノテーション付きクラスにアノテーションを付けることができます。この種の注釈をメタ注釈と呼びます。これは、基本的な注釈、またはラベルのラベル付けに使用される特別なラベルとして理解できます。

Kotlinのメタアノテーションクラスはkotlin.annotation パッケージで定義されて おり、主に次のものが含まれます:  @ Target@ Retention@ Repeatable@ MustBeDocumented  Javaの5種類のメタアノテーションと比較して、4種類のメタアノテーション:  @Target@Retention@Repeatable@Documented、** @ **継承 @Inheritedメタアノテーションがされて行方不明

5.1@Targetメタアノテーション

ターゲットは、その名前が示すように、ターゲットオブジェクトであり、このタグが作用するコードのターゲットオブジェクトです。複数のターゲットオブジェクトを同時に指定できます。

@Target(AnnotationTarget.ANNOTATION_CLASS)//可以给标签自己贴标签
@MustBeDocumented
//注解类构造器参数是个vararg不定参数修饰符,所以可以同时指定多个作用的目标对象
public annotation class Target(vararg val allowedTargets: AnnotationTarget)

@Targetメタアノテーションのターゲットオブジェクト

@Targetアノテーションで同時に1つ以上のターゲットオブジェクトを指定できるので、どのターゲットオブジェクトがありますか?これにより、別のAnnotationTarget 列挙クラスが作成されます。

public enum class AnnotationTarget {
    CLASS, //表示作用对象有类、接口、object对象表达式、注解类
    ANNOTATION_CLASS,//表示作用对象只有注解类
    TYPE_PARAMETER,//表示作用对象是泛型类型参数(暂时还不支持)
    PROPERTY,//表示作用对象是属性
    FIELD,//表示作用对象是字段,包括属性的幕后字段
    LOCAL_VARIABLE,//表示作用对象是局部变量
    VALUE_PARAMETER,//表示作用对象是函数或构造函数的参数
    CONSTRUCTOR,//表示作用对象是构造函数,主构造函数或次构造函数
    FUNCTION,//表示作用对象是函数,不包括构造函数
    PROPERTY_GETTER,//表示作用对象是属性的getter函数
    PROPERTY_SETTER,//表示作用对象是属性的setter函数
    TYPE,//表示作用对象是一个类型,比如类、接口、枚举
    EXPRESSION,//表示作用对象是一个表达式
    FILE,//表示作用对象是一个File
    @SinceKotlin("1.1")
    TYPEALIAS//表示作用对象是一个类型别名
}

5.2@Retentionメタアノテーション

保持の英語の意味は保持期間に対応します。注釈に適用されると、注釈の保持期間を示します。JavaまたはKotlinのいずれの場合でも、通常、ソースコード期間(SOURCE)コンパイル期間の3つの期間があります。  (BINARY)、およびランタイム期間(RUNTIME)

@Target(AnnotationTarget.ANNOTATION_CLASS)//目标对象是注解类
public annotation class Retention(val value: AnnotationRetention = AnnotationRetention.RUNTIME)//接收一个参数,该参数有个默认值,默认是保留在运行时期

@Retentionメタアノテーション値

@Retentionメタアノテーションの値は、主にAnnotationRetention 列挙型クラスから取得 されます

public enum class AnnotationRetention {
    SOURCE,//源代码时期(SOURCE): 注解不会存储在输出class字节码中
    BINARY,//编译时期(BINARY): 注解会存储出class字节码中,但是对反射不可见
    RUNTIME//运行时期(RUNTIME): 注解会存储出class字节码中,也会对反射可见, 默认是RUNTIME
}

5.3@MustBeDocumentedメタアノテーション

このアノテーションは比較的単純で、主にパブリックAPIの一部としてアノテーションクラスをマークし、生成されたAPIドキュメントにアノテーションが存在することを確認します。

@Target(AnnotationTarget.ANNOTATION_CLASS)//目标对象只能是注解类
public annotation class MustBeDocumented

5.4@Repeatableメタアノテーション

この宛先アノテーションのアノテーションは、1つのコード要素の1つのアノテーションに2回以上適用できます。

@Target(AnnotationTarget.ANNOTATION_CLASS)//目标对象只能是注解类
public annotation class Repeatable

5.5KotlinがJavaで@AliExpressメタアノテーションを削除した理由

Javaでの@AliExpressメタアノテーションの概要

Inheriedは、その名前が示すように、継承を意味しますが、アノテーションクラスを継承できることを意味するわけではありませんが、親クラスが@Addedメタアノテーションタグでタグ付けされている場合、そのサブクラスにはアノテーションタグがありません。サブクラスは、親クラスからアノテーションを継承します。

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}

@TestAnnotation
class Animal {
    //...
}

class Cat extends Animal{//也会拥有来自父类Animal的@TestAnnotation注解
    //...
}

Kotlinが@AliExpressメタアノテーションを必要としないのはなぜですか?

実際、Kotlinの公式Webサイトでのディスカッションで、誰かがこの質問を提起しました。興味がある場合は、継承された注釈やその他の反射の強化を確認してください

これがおそらく理由です。Javaでは、サブクラスのメソッドが親クラスのメソッドをオーバーライドするかどうかを見つけることが不可能であることは誰もが知っています。したがって、親メソッドのアノテーションは継承できません。ただし、リフレクションがoverride マークを提供し、簡単に実行できる場合、Kotlinはサポートできるため、Kotlinは現在この@AliExpressメタアノテーションをサポートする必要はありません

6.アノテーションの使用シナリオ

  • コンパイラーに情報を提供する:コンパイラーは、注釈を使用して、警告メッセージやエラーなどの一部を処理できます。
  • コンパイル段階での処理:アノテーション情報を使用してコードを生成します。Kotlinでコードを生成することは非常に一般的です。JavaAPIとの相互運用性のために、コンパイル段階で追加のコードを生成するために、組み込みのアノテーションがよく使用されます。
  • 実行時処理:一部の注釈を使用して、リフレクションメカニズムを介して注釈情報を取得し、プログラムの実行時に一部のプログラムロジックを処理できます。

 

 

 

おすすめ

転載: blog.csdn.net/PrisonJoker/article/details/114004655