ZetCode

Kotlin 注解关键字

最后修改于 2025 年 4 月 19 日

Kotlin 中的注解提供了一种将元数据附加到代码元素的方式。annotation 关键字用于声明自定义注解。本教程通过实际例子深入探讨了注解。

基本定义

注解是提供关于代码元素元数据的特殊属性。它们不直接影响程序执行,但可以被工具或框架处理。Kotlin 支持内置和自定义注解。

内置 @Deprecated 注解

Kotlin 提供了几个内置注解。@Deprecated 注解标记不再使用的元素。它通过警告用户过时代码来帮助 API 演进。

DeprecatedExample.kt
package com.zetcode

@Deprecated("Use newFunction() instead", ReplaceWith("newFunction()"))
fun oldFunction() {
    println("This is the old function")
}

fun newFunction() {
    println("This is the new function")
}

fun main() {
    oldFunction() // Warning: 'oldFunction()' is deprecated
}

这里,我们使用消息和替换建议将 oldFunction 标记为已弃用。当使用此函数时,IDE 将显示警告。替换建议帮助用户迁移到新的 API。

创建自定义注解

自定义注解使用 annotation 关键字声明。它们可以应用于类、函数、属性和其他代码元素。注解可以具有带默认值的参数。

CustomAnnotation.kt
package com.zetcode

annotation class Author(val name: String, val date: String = "2025")

@Author(name = "Jan Bodnar", date = "2025-04-19")
class Document {
    @Author(name = "Jan Bodnar")
    fun print() {
        println("Document printed")
    }
}

fun main() {
    val doc = Document()
    doc.print()
}

我们创建了一个带有两个参数的 Author 注解。该注解同时应用于类和方法。日期参数有一个默认值。像这样的注解可以被文档工具处理。

注解目标规范

Kotlin 允许使用 @Target 指定注解可以应用于哪里。这确保了注解被正确使用,并防止误用于无效目标。

TargetAnnotation.kt
package com.zetcode

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ApiEndpoint(val path: String)

@ApiEndpoint("/users")
class UserController {
    @ApiEndpoint("/list")
    fun listUsers() {
        println("Listing users")
    }
}

fun main() {
    val controller = UserController()
    controller.listUsers()
}

ApiEndpoint 注解仅限于类和函数。尝试将其应用于属性会导致编译错误。这有助于保持一致的 API 设计。

注解保留策略

注解可以使用 @Retention 指定它们的保留策略。这决定了注解在运行时是否可用,或者仅在编译期间可用。

RetentionExample.kt
package com.zetcode

@Retention(AnnotationRetention.RUNTIME)
annotation class RuntimeVisible

@Retention(AnnotationRetention.SOURCE)
annotation class SourceOnly

@RuntimeVisible
@SourceOnly
class TestClass

fun main() {
    val annotations = TestClass::class.annotations
    annotations.forEach { println(it) } // Only shows RuntimeVisible
}

这里,我们定义了两个具有不同保留策略的注解。只有 RuntimeVisible 在运行时可访问。SourceOnly 注解在编译后被丢弃,不会出现在反射中。

可重复注解

Kotlin 支持可重复注解,当使用 @Repeatable 标记时。这允许将相同的注解多次应用于单个元素。

RepeatableAnnotation.kt
package com.zetcode

@Repeatable
annotation class Tag(val name: String)

@Tag("database")
@Tag("performance")
@Tag("security")
class DatabaseService {
    fun connect() {
        println("Connecting to database")
    }
}

fun main() {
    val service = DatabaseService()
    service.connect()
}

Tag 注解被标记为可重复,允许多个标签应用于 DatabaseService 类。此模式对于分类或将多个元数据属性添加到元素非常有用。

注解参数

注解参数可以是基本类型、字符串、枚举、其他注解或这些类型的数组。参数在注解的主构造函数中定义。

AnnotationParams.kt
package com.zetcode

enum class Priority { LOW, MEDIUM, HIGH }

annotation class Scheduled(
    val cron: String,
    val priority: Priority = Priority.MEDIUM,
    val enabled: Boolean = true
)

@Scheduled(cron = "0 * * * *", priority = Priority.HIGH)
class BackgroundTask {
    fun execute() {
        println("Task executed")
    }
}

fun main() {
    val task = BackgroundTask()
    task.execute()
}

Scheduled 注解演示了各种参数类型。它包括一个必需的 cron 表达式和可选的优先级和启用参数。默认值使某些参数在使用注解时变为可选。

注解使用站点目标

在 Kotlin 中,您可以在注解属性时指定注解的适用位置。这是使用带有 @ 符号的使用站点目标完成的。

UseSiteTarget.kt
package com.zetcode

annotation class Positive

class Account {
    @set:Positive
    var balance: Int = 0
        set(value) {
            require(value >= 0) { "Balance must be positive" }
            field = value
        }
}

fun main() {
    val account = Account()
    account.balance = 100
    println("Balance: ${account.balance}")
}

这里,@Positive 注解应用于 balance 属性的 setter。使用站点目标(如 @set@get@field)提供了对注解放置的精确控制。

注解的最佳实践

来源

Kotlin 注解文档

本教程深入介绍了 Kotlin 的 annotation 关键字,展示了内置和自定义注解。我们探讨了各种注解特性,包括目标、保留和参数。正确使用注解可以增强代码文档并启用强大的元编程功能。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我写了超过 1400 篇文章和 8 本电子书。我有超过八年的编程教学经验。

列出 所有 Kotlin 教程