元注解
@Retention 保留期
- AnnotationRetention.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 常用于代码检测。
- AnnotationRetention.BINARY 注解被编译到二进制文件,但不会被加载到 JVM 中。 反射不可见。
- AnnotationRetention.RUNTIME 注解被编译到二进制文件,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。默认值。可用于运行时反射获取注解信息。
@Target 作用域
定义该注解可使用的领域
- AnnotationTarget.CLASS 可以给一个类型进行注解,类、接口、对象、甚至注解类本身
- AnnotationTarget.ANNOTATION_CLASS 可以给一个注解类进行注解
- AnnotationTarget.TYPE_PARAMETER 泛型参数(暂未支持)
- AnnotationTarget.VALUE_PARAMETER 方法、构造函数的参数
- AnnotationTarget.PROPERTY (计算)属性(该注解Java不可见)
- AnnotationTarget.PROPERTY_GETTER 属性getter方法
- AnnotationTarget.PROPERTY_SETTER 属性setter方法
- AnnotationTarget.FIELD 字段变量,包括PROPERTY的备用字段(backing field)
- AnnotationTarget.LOCAL_VARIABLE 局部变量
- AnnotationTarget.CONSTRUCTOR 构造函数
- AnnotationTarget.FUNCTION 方法、函数(不包括构造函数)
- AnnotationTarget.FILE 文件整体
- AnnotationTarget.TYPE 泛型支持
- AnnotationTarget.TYPEALIAS typealias类型
- AnnotationTarget.EXPRESSION 表达式
@MustBeDocumented
将注解中的元素包含到 Javadoc 中去。
@Repeatable
该注解允许复数应用到同一目标(通过提供不同注解参数区分)
AbstractProcessor 注解处理器
派生该处理器子类,复写以下方法:
-
getSupportedAnnotationTypes
返回该处理器负责的目标注解类 -
getSupportedSourceVersion
返回可使用该处理器的Java版本,一般返回SourceVersion.latest
-
init
环境初始化 -
process
主要的逻辑实现方法
※ 使用 AutoService 将注解处理器注册到META-INF元数据中
@AutoService(Processor::class)
class MyProcessor: AbstractProcessor() {
override fun getSupportedAnnotationTypes(): MutableSet<String> {
return mutableSetOf(MyAnnotation::class.java.name)
}
override fun getSupportedSourceVersion(): SourceVersion {
return SourceVersion.latest()
}
override fun process(set: MutableSet<out TypeElement>,
roundEnv: RoundEnvironment): Boolean {
roundEnv.getElementsAnnotatedWith(GenName::class.java)
.forEach {
val className = it.simpleName.toString()
val pack = processingEnv.elementUtils.getPackageOf(it).toString()
// else
}
return true
}
}
自定义注解
定义
注解支持的参数类型:
- 基本类型
- 字符串
- Kotlin类(KClass)
- 枚举
- 其他注解
- 上述类型的数组
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
使用
// 一般用法
@Fancy class Foo {
@Fancy fun baz(@Fancy foo: Int): Int {
return (@Fancy 1)
}
}
// 构造函数
class Foo @Inject constructor(dependency: MyDependency) {
}
// 属性setter
class Foo {
var x: MyDependency? = null
@Inject set
}
// Lambda表达式
val f = @Suspendable { Fiber.sleep(10) }
指定注解作用域
在使用注解时,可显式指定该注解的作用范围。
-
file
注解整个文件时指定 -
property
(计算)属性(该注解对 Java 不可见) -
field
字段 -
get
属性 getter -
set
属性 setter -
receiver
扩展函数或属性的接收者 -
param
构造函数参数 -
setparam
属性 setter 参数 -
delegate
委托属性存储其委托实例的字段
对PROPERTY属性或构造函数参数使用注解时,可显式指定其作用域:
class Example(@field:Ann val foo, // 标注 Java 字段
@get:Ann val bar, // 标注 Java getter
@param:Ann val quux) // 标注 Java 构造函数参数
对整个文件进行注解:
@file:JvmName("Foo")
package org.jetbrains.demo
同一目标多重注解时,使用数组式声明:
class Example {
@set:[Inject VisibleForTesting]
var collaborator: Collaborator
}
不指定作用域时,根据注解定义的Target选择应用目标。当存在多个可应用目标时,适配以下第一个合适的对象:
param
property
field
网友评论