0Pricing
Kotlin Academy · レッスン

実行時にアノテーションを読み取る

Kotlinリフレクションを使って宣言からアノテーションのインスタンスを取得します。

「実行時にアノテーションを読み取る」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。

前提条件

実行時にアノテーションを読み取るには、次のものが必要です。(1) @Retention(RUNTIME)を付けて宣言したアノテーション、(2) クラスパス上のkotlin-reflect依存関係、(3) アノテーションが付いた要素へのKClass、KFunction、またはKProperty参照です。

KClassからアノテーションを読み取る

KClassに対してannotationsを呼び出すと、そのクラスに付いたすべてのアノテーションを取得できます。特定の型にはfindAnnotation<T>()を使用します。

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Table(val name: String)

@Table(name = "users")
class UserEntity

val ann = UserEntity::class.findAnnotation<Table>()
println(ann?.name)  // "users"

プロパティからアノテーションを読み取る

KProperty.annotationsまたはfindAnnotation<T>()を使って、プロパティのアノテーションにアクセスします。

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Column(val name: String)

data class User(@Column("user_name") val name: String)

val prop = User::name
val col = prop.findAnnotation<Column>()
println(col?.name)  // "user_name"

関数からアノテーションを読み取る

KFunction.findAnnotation<T>()を使って、関数に付いたアノテーションを読み取ります。

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Transactional

class UserService {
    @Transactional
    fun save(user: User) { /*...*/ }
}

val fn = UserService::save
val isTx = fn.hasAnnotation<Transactional>()
println(isTx)  // true

すべてのプロパティを調べてアノテーションを取得する

よく使われるパターンは、クラスで宣言されたすべてのプロパティを調べ、特定のアノテーションが付いたものを収集することです。

fun <A : Annotation> KClass<*>.annotatedProperties(
    annotationClass: KClass<A>
): List<Pair<KProperty1<*, *>, A>> =
    declaredMemberProperties
        .mapNotNull { prop ->
            prop.findAnnotation(annotationClass)?.let { ann -> prop to ann }
        }

パラメータのアノテーションを読み取る

KFunction.parametersを使って、コンストラクタパラメータのアノテーションにアクセスします。

class Repo(
    @param:Validate(minLength = 3) val name: String
)

val ctor = Repo::class.primaryConstructor!!
val param = ctor.parameters.first()
val ann = param.findAnnotation<Validate>()
println(ann?.minLength)  // 3

hasAnnotationとfindAnnotation

真偽値だけを確認する場合はhasAnnotation<T>()を使用し、アノテーションのプロパティ値が必要な場合はfindAnnotation<T>()を使用します。どちらもkotlin.reflect.fullの拡張関数です。

クラス階層をたどる

スーパークラスやインターフェースのアノテーションは、Kotlinリフレクションでは自動的に継承されません。継承されたアノテーションが必要な場合は、KClass.superclassesをたどるか、KClass.allSuperclassesを使用する必要があります。

fun KClass<*>.findAnnotationRecursive(ann: KClass<out Annotation>) =
    generateSequence(this) { null } // simplified — real impl walks supers
        .flatMap { it.annotations }
        .firstOrNull { it.annotationClass == ann }

パフォーマンス

リフレクションの呼び出しは低速です。フレームワークの起動時にアノテーションを調べる場合は、結果をKClassをキーとするマップにキャッシュしてください。リクエストごと、またはフレームごとに実行される処理でアノテーションを読み取ることは避けてください。

use-siteターゲットとJVMフィールド

@field:ターゲットを持つプロパティのアノテーションは、JVMのバッキングフィールドに置かれます。Kotlinの宣言サイトだけを対象とするannotationsリストではなく、Javaリフレクション(KProperty.javaField?.annotations)を使ってアクセスしてください。

実践例:シンプルなORMマッパー

小さなORMマッパーが@Columnアノテーションを読み取り、SQLのカラムリストを構築します。

fun columns(klass: KClass<*>): String =
    klass.declaredMemberProperties
        .mapNotNull { it.findAnnotation<Column>()?.name }
        .joinToString(", ")

println(columns(User::class))  // "user_name, email"

クイックチェック

KClassから、MyAnn型の特定のアノテーションをどのように読み取りますか?

まとめ:実行時にアノテーションを読み取る

主なポイント:

  • アノテーションには@Retention(RUNTIME)が必要
  • findAnnotation<T>()でアノテーションの値を取得し、hasAnnotation<T>()で真偽値を確認する
  • KClass、KFunction、KProperty、KParameterで使用できる
  • リクエストごとのオーバーヘッドを避けるため、起動時にスキャン結果をキャッシュする
  • @field:アノテーションにはKProperty.javaFieldを使用する

よくある質問

「実行時にアノテーションを読み取る」レッスンは無料ですか?

はい。「実行時にアノテーションを読み取る」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。

「実行時にアノテーションを読み取る」で何を学びますか?

Kotlinリフレクションを使って宣言からアノテーションのインスタンスを取得します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Kotlin Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「実行時にアノテーションを読み取る」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このKotlin Academyレッスンでコードを書いて実行できますか?

はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Kotlin Reflection:KClass、KFunction、KProperty
  2. カスタムアノテーションの作成と対象指定
  3. 実行時にアノテーションを読み取る
  4. リフレクションベースのバリデーションとマッピング
← Kotlin Academyに戻る