Kotlin进阶知识(十二)——声明并应用注解

1、应用注解

在Kotlin中使用注解的方法和Java同样。要应用一个注解,以**@字符做为(注解)名字的前缀**,并放在要注解的声明最前面git

注解只能拥有以下类型的参数:基本数据类型字符串枚举类引用其余的注解类,以及前面这些类型数组github

指定注解实参的语法与Java有些微小的差异:json

  • 要把一个类指定为注解实参,在类名后加上**::class: @MyAnnotation(MyClass::class)**。
  • 要把另外一个注解指定为一个实参去掉注解名称前面的@
  • 要把一个数组指定为一个实参,使用**arrayOf函数**:@RequestMapping(path = arrayOf("/foo", "/bar"))

注解实参须要在编译期就是已知的,因此不能引用任意的属性做为实参。要把属性看成注解实参使用,须要用**const修饰符标记它,来告知编译器这个属性编译期变量**。数组

const val TEST_TIMEOUT = 100L

@Test(timeout = TEST_TIMEOUT) fun testMethod() { ... }
复制代码

2、注解目标

使用点目标声明被用来说明要注解的元素。使用点目标被放在**@符号注解名称之间,并用冒号和注解名称隔开**,如图1。markdown

图1:说明使用点目标的语法

class HasTempFolder {
    // 注解的是getter,而不是属性。
    @get: Rule
    val folder = TemporaryFolder()

    @Test
    fun testUsingTempFolder() {
        // ...
    }
}
复制代码

注:上述代码需使用JUnit框架app

使用Java中声明的注解来注解一个属性,它会被默认地应用到相应的字段上。Kotlin也可让你声明被直接对应到属性上的注解。框架

Kotlin支持的使用点目标的完整列表以下:函数

  • property:Java的注解不能应用这种使用点目标。
  • field:为属性生成的字段
  • get:属性的getter
  • set: 属性的setter
  • receiver扩展函数或者扩展属性接受者参数
  • param构造方法的参数
  • setparam: **属性setter**的参数
  • delegate: 为委托属性存储委托实例的字段
  • file: 包含在文件中声明的顶层函数和属性的类

注意:任何应用到file目标的注解都必须放在文件的顶层,放在**package指令以前**。oop

用注解控制JavaAPI Kotlin提供了各类注解来控制Kotlin编写的声明如何编译成字节码并暴露给Java调用者。spa

  • @JvmName 将改变由**Kotlin生成的Java方法或字段的名称**
  • @JvmStatic 能被用在对象声明或者伴生对象方法上,把它们暴露成**Java的静态方法**
  • @JvmOverloads 指导Kotlin编译器为带默认参数值的函数生成多个重载(函数)
  • @JvmField 能够应用于一个属性,把这个属性暴露成一个没有访问器的公有Java字段

3、声明注解

annotation class JsonExclude
复制代码

语法看起来和常规类的声明很像,只是在class关键字以前加上了**annotation修饰符**。由于注解类只是用来定义关联到声明和表达式元数据的结构,它们不能包含**任何代码**。所以编译器禁止为一个注解类指定类主体。

4、元注解:控制如何处理一个注解

和Java同样,一个Kotlin注解类本身也能够被注解。能够应用到注解类上的注解被称做元注解。

标准库定义的元注解中最多见的就是@Target。JKid中@JsonExclude和@JsonName的声明使用它为这些注解指定有效的目标。

@Target(AnnotationTarget.PRIPERTY)
annotation class JsonExclude
复制代码

注:@JsonExclude 是 JKid库中的方法

@Target元注解说明了注解能够被应用的元素类型。若是不使用它全部的声明均可以应用这个注解。这并非JKid想要的,由于它只须要处理属性的注解。

5、使用泛型类作注解参数

@CustomSerializer注解接受一个自定义序列化器类的引用做为实参

interface ValueSerializer<T> {
    fun toJsonValue(value: T): Any?
    fun fromJsonValue(jsonValue: Any?): T
}

data class PersonAnnotation(
    val name: String,
    @CustomSerializer(DateSerializer::class) val birthDate: Date
)

// @CustomSerializer底层源码
annotation class CustomSerializer(
    val serializerClass: KClass<out ValueSerializer<*>>
)
复制代码
相关文章
相关标签/搜索