Kotlin基础——注解和反射

声明并应用注解

应用注解

同Java一样,注解放到函数或类最前面

class MyTest {
    @TestOnly
    fun test() {
        
    }
}

@Deprecated可以提供实参,且通过ReplaceWith为IDEA提示正确的用法

class MyTest{
    @Deprecated("Use removeAt(index) instead.",ReplaceWith("removeAt(index)"))
    fun remove(index: Int) {
    
    }
    fun removeAt(index: Int) {
    
    }
}

在这里插入图片描述

注解的参数类型为:基本数据类型、字符串、枚举、类引用、其他的注解类,以及他们的数组,但需要注意

  • 类作为参数时,类名后加上::class
  • 注解作为参数时,不用加上@,如上面Deprecated中的ReplaceWith也是一个注解
  • 数组作为参数时,需使用arrayOf函数,如@RequestMapping(path = arrayOf(“/foo”,“/bar”))
  • 注解实参需要在编译期已知,若使用属性则需使用const修饰为常量

注解目标

Koltin的单个声明会对应Java多个声明(如一个Kotlin属性对应一个Java字段、getter、setter)

要限制注解的使用范围,需通过使用点目标声明,使用点目标被放在@符号和注解名词之间,并用冒号隔开,如下表示注解应用于属性的getter

在这里插入图片描述
完整的使用点目标如下

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

Java的注解只能用于类和函数的声明,而Kotlin允许对任意的表达式应用注解,如用于局部变量

  • @Volatile、@Strictfp代替Java的volatile、strictfp关键字
  • @file:JvmName(“Abc”)用于修改顶层函数生成的类的名称,否则Xxx.kt默认为XxxKt.class,添加注解后为Abc.class
  • @JvmStatic用在对象声明或者伴生对象的方法上,让其变成Java的静态方法
  • @JvmOverloads为带默认参数值的函数生成多个重载函数
  • @JvmField将属性变成一个公有Java字段

注解声明

以下用加载JSON的JKid库中的注解进行讲解,注解没有类实体,若存在参数,则必定为val

annotation class JsonExclude		//不参与序列化
annotation class JsonName(val name: String)     //修改JSON中key-value中的key

元注解

注解类自己也可以被注解,应用到注解类上的注解被称为元注解,如下使用@Target标识@JsonExclude只能用于属性

  • Java中无PROPERTY,如果属性需要用于Java,则需要指定FIELD
@Target(AnnotationTarget.PROPERTY)
annotation class JsonExclude

若要声明自己的元注解,需要使用AnnotationTarget.ANNOTATION_CLASS

@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class BindingAnnotation

@BindingAnnotation
annotation class MyBinding

@Retention元注解在Java中表示注解是否会存储到.class文件以及能否在运行时通过反射来访问,而Kotlin默认注解有Rumtime保留期

使用类作为注解参数

需要使用out指定可接受子类型,否则只能使用Any

annotation class DeserializeInterface(val targetClass: KClass<out Any>)

使用泛型类作为注解参数

默认情况下,非基本数据类型的属性会被当成嵌套的对象序列,如果需要自定义序列化方式,则应该实现序列化器接口ValueSerializer,同时@CustomSerializer支持所有ValueSerializer的泛型子类

interface ValueSerializer<T> {
    fun toJsonValue(value: T): Any?
    fun fromJsonValue(jsonValue: Any?): T
}
annotation class CustomSerializer(val serializerClass: KClass<out ValueSerializer<*>>)

反射

反射是一种运行时动态地访问对象属性和方法的方式

KClass

可通过如下两种方式获取KClass

val kClass1 = Person::class
println(kClass1.simpleName)

val person = Person("A", 1)
val kClass2 = person.javaClass.kotlin
println(kClass2.simpleName)

KCallable

可通过members获取所有属性和方法(需根据IDEA提示添加kotlin-reflect.jar),其都是KCallable的子类型

class Person(val name: String, val age: Int)

val kClass = Person::class
val members = kClass.members
members.forEach { println(it) }

如上打印(代码在Android的MainActivity运行)

val com.demo.demo1.`MainActivity$onCreate$Person`.age: kotlin.Int
val com.demo.demo1.`MainActivity$onCreate$Person`.name: kotlin.String
fun com.demo.demo1.`MainActivity$onCreate$Person`.equals(kotlin.Any?): kotlin.Boolean
fun com.demo.demo1.`MainActivity$onCreate$Person`.hashCode(): kotlin.Int
fun com.demo.demo1.`MainActivity$onCreate$Person`.toString(): kotlin.String

KFunction

::foo是一个KFunction1<Int,Unit>实例,1表示参数个数,<int,Unit>表示参数和返回值类型,继承KCallable,其call()方法允许你调用对应的函数或者对应属性的getter

fun foo(x: Int) = println(x)
val kFunction = ::foo
kFunction.call(1)

call()不提供类型检查和参数数量检查,若传入错误的值,会在运行时报错,而通过invoke()或直接调用KFunction可在编译时提示错误

fun sum(x: Int, y: Int) = x + y
val kFunction = ::sum
println(kFunction.invoke(1, 2) + kFunction(3, 4))

KProperty

顶层属性为KProperty0接口实例,可通过call()调用getter,或通过反射调用setter,也可直接调用get()

var counter = 0
val kProperty = ::counter
println(kProperty.call())
kProperty.setter.call(21)

println(kProperty.get())

成员属性为KProperty1<Person,Int>接口实例,访问时需提供所属对象的实例

class Person(val name: String, val age: Int)

val person = Person("A", 1)
val kProperty = Person::age
println(kProperty.get(person))

获取注解


  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值