Аннотации в Kotlin
Для чего нужны?
Аннотации добавляют метаданные к классам, функциям или свойствам. Они используются:
- Для генерации кода (например, сериализация)
- Контроля поведения компилятора
- Интеграции с фреймворками (Spring, Ktor)
- Документирования специальных условий
Объявление аннотаций
Базовая аннотация
Пример объявления
annotation class ExperimentalFeature
Аннотация с параметрами
Параметры как в конструкторе
annotation class Route(
val path: String,
val method: HttpMethod = HttpMethod.GET
)
Правила
- Параметры могут иметь только базовые типы и массивы
- Для массивов используйте
arrayOf()
вместо{}
- Нельзя объявлять
var
параметры
Использование в коде
Маркировка элементов
Пример применения
@ExperimentalFeature
class NewAuthService { ... }
@Route("/users", HttpMethod.POST)
fun createUser() { ... }
Целевые указатели
Уточнение цели для свойства
class User(
@get:JsonExpose
val name: String
)
Массивы аннотаций
Несколько аннотаций
@Deprecated("Use newMethod() instead")
@Suppress("UNCHECKED_CAST")
fun legacyMethod() { ... }
Популярные встроенные аннотации
Контроль совместимости
Примеры
@JvmStatic // Генерирует статический метод для Java
@JvmName("parseXML") // Меняет имя метода в байткоде
Обработка null
Специфика Kotlin
@NonNull // Требует non-null значение (для Java интеграции)
@Nullable // Разрешает null (для Java интеграции)
Сериализация
Пример для библиотеки kotlinx.serialization
@Serializable
data class Project(val id: Int, val name: String)
Продвинутые сценарии
Аннотации и рефлексия
Получение аннотаций через reflection
val annotations = User::class.annotations
annotations.find { it is Route }?.let { ... }
Создание обработчиков
Пример обработчика (kapt/kotlinpoet)
annotation class BuilderProperty // Генерирует builder-методы
Мета-аннотации
Аннотация для аннотаций
@Target(AnnotationTarget.CLASS) // Где можно применять
@Retention(AnnotationRetention.SOURCE) // Когда доступна
annotation class DatabaseEntity
Ограничения и советы
- Доступ во время выполнения: По умолчанию аннотации удаляются из байткода.
Используйте@Retention(AnnotationRetention.RUNTIME)
для сохранения. - Производительность: Избегайте сложной логики в обработчиках аннотаций.
- Java-совместимость: Для аннотаций с массивами используйте
@JvmSuppressWildcards
. - Порядок параметров:
// Неправильно:
@Ann(targets = [FIELD], message = "Test")
// Правильно:
@Ann(targets = arrayOf(FIELD), message = "Test")