Практическая рефлексия
Динамически читайте аннотации
«Практическая рефлексия» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Аннотации и рефлексия
Аннотацию с сохранением RUNTIME можно обнаружить во время выполнения с помощью рефлексии. Это сочетание лежит в основе сериализаторов, средств проверки и внедрения зависимостей.
В этом уроке мы динамически прочитаем собственные аннотации.
Чтение аннотации класса
Каждый KClass предоставляет список annotations. Мы можем просмотреть его и найти аннотацию определённого типа.
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity(val table: String)
@Entity("users")
class User
fun main() {
val ann = User::class.annotations
.filterIsInstance<Entity>()
.first()
println(ann.table)
}Вспомогательная функция findAnnotation
Расширение findAnnotation удобнее, чем фильтрация вручную. Оно возвращает аннотацию или null.
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity(val table: String)
@Entity("orders")
class Order
fun main() {
val ann = Order::class.findAnnotation<Entity>()
println(ann?.table)
}Аннотации свойств
У свойств есть собственные аннотации. Переберите memberProperties и изучите annotations каждого свойства.
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Column(val name: String)
class Product(@Column("product_id") val id: Int, val title: String)
fun main() {
Product::class.memberProperties.forEach { prop ->
val col = prop.findAnnotation<Column>()
if (col != null) println(prop.name + " -> " + col.name)
}
}Создание мини-сериализатора
Объедините чтение свойств с аннотациями, чтобы создать результат. Здесь мы преобразуем каждое свойство в строку key=value, используя имя столбца, если оно указано.
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Column(val name: String)
class Item(@Column("item_id") val id: Int, val name: String)
fun main() {
val item = Item(7, "Book")
val parts = Item::class.memberProperties.map { p ->
val key = p.findAnnotation<Column>()?.name ?: p.name
key + "=" + p.getter.call(item)
}
println(parts.joinToString(", "))
}Пропуск с помощью маркера
Аннотация-маркер может указывать, какие свойства нужно игнорировать. Мы проверяем её наличие с помощью hasAnnotation.
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.hasAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Transient2
class Account(val id: Int, @Transient2 val secret: String)
fun main() {
Account::class.memberProperties
.filterNot { it.hasAnnotation<Transient2>() }
.forEach { println(it.name) }
}Чтение аргументов аннотаций
Получив экземпляр аннотации, Вы увидите, что её параметры являются обычными свойствами. Читайте их так же, как любое поле.
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Validated(val min: Int, val max: Int)
@Validated(min = 1, max = 100)
class Quantity
fun main() {
val v = Quantity::class.findAnnotation<Validated>()!!
println("range " + v.min + ".." + v.max)
}Аннотации функций
Функции также можно аннотировать и изучать. Платформы используют это, чтобы находить обработчики, например средства запуска тестов находят методы для тестирования.
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Route(val path: String)
class Api {
@Route("/home")
fun home() = "home page"
}
fun main() {
Api::class.memberFunctions.forEach { f ->
f.findAnnotation<Route>()?.let { println(f.name + " @ " + it.path) }
}
}Управление поведением
Прочитайте аннотацию маршрута и фактически отправьте вызов. В этом заключается суть работы платформ маршрутизации.
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.full.findAnnotation
@Retention(AnnotationRetention.RUNTIME)
annotation class Route(val path: String)
class Api {
@Route("/ping")
fun ping() = "pong"
}
fun main() {
val api = Api()
val target = "/ping"
Api::class.memberFunctions.forEach { f ->
if (f.findAnnotation<Route>()?.path == target) {
println(f.call(api))
}
}
}Применение в реальных проектах
Рефлексия на основе аннотаций лежит в основе многих библиотек:
- Сериализация JSON, сопоставляющая поля с ключами
- Проверка, обеспечивающая соблюдение ограничений
- Маршрутизация, сопоставляющая пути с обработчиками
- Внедрение зависимостей, связывающее компоненты
Используйте рефлексию целенаправленно
Лучше всего ограничивать рефлексию настройкой и кодом платформы, который выполняется один раз или редко. По возможности кэшируйте результаты. Для часто выполняемых участков обработки запросов предпочитайте обработку во время компиляции.
Быстрая проверка
Проверьте, насколько хорошо Вы поняли практическое применение рефлексии.
Итоги
Вы объединили аннотации и рефлексию, чтобы:
- Находить аннотации классов, свойств и функций
- Читать аргументы аннотаций во время выполнения
- Создать мини-сериализатор и диспетчер маршрутов
- Пропускать поля с аннотациями-маркерами
Так создаются настоящие платформы.
Часто задаваемые вопросы
Урок «Практическая рефлексия» бесплатный?
Да — полный текст урока «Практическая рефлексия» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Практическая рефлексия»?
Динамически читайте аннотации Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Практическая рефлексия»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Использование аннотаций
- Определение аннотаций
- Основы рефлексии
- Практическая рефлексия