0Pricing
Kotlin Academy · Урок

Чтение аннотаций во время выполнения

Получайте экземпляры аннотаций из объявлений с помощью рефлексии Kotlin.

«Чтение аннотаций во время выполнения» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Предварительные требования

Чтобы читать аннотации во время выполнения, необходимо: (1) объявить аннотацию с помощью @Retention(RUNTIME), (2) добавить зависимость kotlin-reflect в путь к классам и (3) получить ссылку KClass, KFunction или KProperty на аннотированный элемент.

Чтение аннотаций из KClass

Вызовите annotations у KClass, чтобы получить все аннотации этого класса, или используйте findAnnotation() для конкретного типа:

@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():

@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(), чтобы прочитать аннотации функций:

@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() для проверки логического значения, а findAnnotation() — когда нужны значения свойств аннотации. Обе являются функциями-расширениями из 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. Никогда не читайте аннотации на горячих путях обработки отдельных запросов или кадров.

Цели применения и поля JVM

Для аннотаций свойств с целью @field: аннотация хранится в поле хранения JVM. Получайте её через рефлексию Java (KProperty.javaField?.annotations), а не через список annotations Kotlin, который охватывает только место объявления в Kotlin.

Практический пример: простой сопоставитель 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(), чтобы получить значение аннотации, а hasAnnotation() — для логической проверки
  • Работает с KClass, KFunction, KProperty и KParameter
  • Кэшируйте результаты просмотра при запуске, чтобы избежать затрат на каждый запрос
  • Для аннотаций @field: используйте KProperty.javaField

Часто задаваемые вопросы

Урок «Чтение аннотаций во время выполнения» бесплатный?

Да — полный текст урока «Чтение аннотаций во время выполнения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Чтение аннотаций во время выполнения»?

Получайте экземпляры аннотаций из объявлений с помощью рефлексии Kotlin. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Чтение аннотаций во время выполнения»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Рефлексия Kotlin: KClass, KFunction, KProperty
  2. Создание и применение пользовательских аннотаций
  3. Чтение аннотаций во время выполнения
  4. Валидация и отображение на основе рефлексии
← Назад к Kotlin Academy