我们一般使用类和函数要说明类和函数的确切名称。调用一个类,你需要知道它定义在哪个类中,还有它的名称和参数的类型。
注解和反射可以给你超越这个规则的能力,让你编写出使用事先未知的任意类的代码。注解赋予这些类库特定的语义,而反射允许你在运行时分析这些类的结构。
应用注解
// 如@Test标记一个函数 class MyTest{ @Test fun test(){ //TODO } }
注解只能拥有如下类型的参数:基本数据类型、字符串、枚举、类引用、其他的注解类。
//类作为注解实参,要在类名后加 ::class @MyAnnotation(MyClass::class) //另一个注解作为注解实参,去掉@ 这里的ReplaceWith是一个注解 @Deprecated("Use removeAt(index) instead.",ReplaceWith("removeAt(index)"))
注解实参需要在编译期就是已知的,要把属性当做注解实参使用,需要用const修饰符标记它,来告知编译器这个属性是编译常量。
const val TEST_TIMEOUT = 100L @Test(timeout = TEST_TIMEOUT) fun testMethod(){ }
用const标注的属性可以声明在一个文件的顶层或者一个object中,而且必须初始化为基本数据类型或者String类型的值。如果尝试使用普通类的属性作为注解实参,会报错。
注解目标
Kotlin源代码中的单个声明可能会对应成多个声明,比如Kotlin的属性就对应一个Java字段、一个getter、一个潜在的setter和它的参数。而且他们每一个都能携带注解。所以说明这些元素中哪些需要注解十分必要。
//这里Rule是注解名,get是点目标,代表应用到getter上,用冒号隔开它们 @get:Rule
使用注解定制JSON序列化
注解的一个经典用法之一就是定制化对象的序列化。
序列化就是一个过程,把对象转换成可以存储或者在网络上传输的二进制或者文本的表示法。
反序列化就是把这种表示法转换成一个对象。
最常见的一种序列化的格式就是JOSN
//序列化一个Person类 data class Person(val name:String, val age:Int) //把实例传给serialize函数,就会返回一个包含该实例json表示法的字符串 >>>val person = Person("Alice", 20) >>>println(serialize(person)) {"age": 20, name: "Alice"} //反序列化取出一个对象 >>>val json=""" {"age": 20, name: "Alice"} """ >>>println(deserialize<Person>(json)) Person(name=Alice, age=29)
声明注解
annotation class JsonName(val name:String) 在class前加annotation,并且没有类主体i,不需要大括号。
元注解
注解类也可以被注解。应用在注解类上的注解被称为元注解。
链接:Java中的四个元注解