Kotlin注解探秘:让代码更清晰

快速上手

Kotlin 复制代码
@Target(  
 AnnotationTarget.CLASS,  
 AnnotationTarget.FUNCTION,  
 AnnotationTarget.VALUE_PARAMETER,  
 AnnotationTarget.EXPRESSION,  
 AnnotationTarget.CONSTRUCTOR  
)
@Retention(AnnotationRetention.SOURCE)
@Repeatable
@MustBeDocumented
annotation class MyAnnotation

@MyAnnotation @MyAnnotaion class Test @MyAnnotation constructor(val name: String) {
    @MyAnnotation fun test(@MyAnnotation num: Int): Int = (@MyAnnotation 1)
}

注解的声明

注解使用关键字annotation来声明,比如快速上手中的例子,使用annotation class MyAnnotation就声明了一个注解,我们可以按照定义的规则将其放在其他元素身上

元注解

下面的注解了解过Java的肯定不陌生,元注解就是可以放在注解上面的注解

  • @Target: 用来指定注解可以应用到哪些元素上,有以下可选项

    • CLASS: 可以应用于类、接口、枚举类
    • ANNOTATION_CLASS: 可以应用于注解
    • TYPE_PARAMETER
    • PROPERTY
    • FIELD
    • LOCAL_VARIABLE
    • VALUE_PARAMETER: 可以应用于字面值
    • CONSTRUCTOR: 可以应用于构造函数
    • FUNCTION: 可以应用于函数
    • PROPERTY_GETTER
    • PROPERTY_SETTER
    • TYPE
    • EXPRESSION: 可以应用于表达式
    • FILE
    • TYPEALIAS
  • @Retention: 用来指定注解的生命周期

    • SOURCE: 仅保存在源代码中
    • BINARY: 保存在字节码文件中,但是运行是无法获取
    • RUNTIME: 保存在字节码文件中,运行时可以获取
  • @Repeatable: 允许此注解可以在单个元素上多次使用

拿上方的代码来简单介绍几个元注解

@Target

可以看一下@Target的源码

Kotlin 复制代码
 * This meta-annotation indicates the kinds of code elements which are possible targets of an annotation.
 *
 * If the target meta-annotation is not present on an annotation declaration, the annotation is applicable to the following elements:
 * [CLASS], [PROPERTY], [FIELD], [LOCAL_VARIABLE], [VALUE_PARAMETER], [CONSTRUCTOR], [FUNCTION], [PROPERTY_GETTER], [PROPERTY_SETTER].
 *
 * @property allowedTargets list of allowed annotation targets
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
@MustBeDocumented
public annotation class Target(vararg val allowedTargets: AnnotationTarget)

在源码中可以看到,Target注解中要传入的参数为allowedTargets,使用了vararh关键字,可传入多个参数,参数的类型为AnnotationTarget,它是一个枚举类,再进入AnnotationTarget的源码就可以看到它有上方元注解中列出的那些。

在快速上手的示例中我们的@Target中传入了Class FUNCTION VALUE_PARAMETER EXPRESSION CONSTRCTOR,表示此注解可以放在类、接口、枚举、函数、字面值、表达式和构造函数上

@Retention

此注解就是指定它什么时候失效 默认是RUNTIME, 快速上手中是用的SOURCE,表示它仅存在于**「源码」中,在编译成字节码后将会消失,如果指定了BINARY,则可以存在于字节码文件中,但是「运行时无法获取」**,反射无法获取

注解的属性

注解可在主构造参数内传值

Kotlin 复制代码
annotation class MyAnnotation2(val effect: String)

class Test2 {
    @MyAnnotation2("Test")
    fun test() {
        println("Run test")
    }
}

比如上面的例子,可以在主构造函数内传入一个参数,参数支持的类型有以下几种

  • Kotlin中的八种"「基本数据类型」"(Byte, Short, Int, Long, Float, Double, Boolean, Char)
  • **「String」**类型
  • **「引用」**类型(Class)
  • **「枚举」**类型
  • **「注解」**类型
  • 以上类型的**「数组类型」** 需要注意的是,官网中特别说明参数不可以传入可空类型,比如"String?",因为JVM不支持null存储在注解的属性中

注解的作用

如果是熟悉Java的开发者对注解的作用肯定是非常熟悉。 注解可以提供给**「编译器、运行时环境、其他代码库以及框架」提供很多可用信息。 可用作 「标记」,可供第三方技术库、框架识别信息,比如大家熟悉的SpringBoot,很多事情就是通过注解和反射来实现 可用来提供更多的 「上下文信息」**,比如方法的类型参数、返回值类型、错误处理

后面可结合反射来深入理解Kotlin在开发中的用途

相关推荐
有点感觉1 天前
Android级联选择器,下拉菜单
kotlin
zhangphil2 天前
Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(1)
android·kotlin
xvch2 天前
Kotlin 2.1.0 入门教程(二十三)泛型、泛型约束、协变、逆变、不变
android·kotlin
xvch3 天前
Kotlin 2.1.0 入门教程(二十四)泛型、泛型约束、绝对非空类型、下划线运算符
android·kotlin
zhangphil4 天前
Android Coil ImageLoader MemoryCache设置Key与复用内存缓存,Kotlin
android·kotlin
mmsx4 天前
kotlin Java 使用ArrayList.add() ,set()前面所有值被 覆盖 的问题
android·开发语言·kotlin
lavins4 天前
android studio kotlin项目build时候提示错误 Unknown Kotlin JVM target: 21
jvm·kotlin·android studio
面向未来_4 天前
JAVA Kotlin Androd 使用String.format()格式化日期
java·开发语言·kotlin
alexhilton4 天前
选择Retrofit还是Ktor:给Android开发者的指南
android·kotlin·android jetpack
GordonH19915 天前
Kotlin 优雅的接口实现
android·java·kotlin