携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的25天,点击查看活动详情
为了活动小家电,接着上篇搞!
自定义注释(使用反射)
现在我们要创建一个自定义注释。
创建Custom Annotation时,有一种使用Reflection的方法,也有一种使用Code Generation的方法。
反射是一个强大的功能,它会在运行时改变代码结构,但应该谨慎使用,因为它很危险。
反射不是我个人的偏好,因为它会导致应用程序性能不佳。
比如Reflection中,每次调用函数时,都会检查参数个数是否正确,参数类型是否正确等。这会造成性能损失,因为 JIT 编译器每次都会执行它在运行时只会执行一次的操作。当然,现在它快了一点,但我还是不建议过度使用它。
在 Kotlin 中使用反射最基本的方法是使用 KClass。
如果只使用KClass,运行时会崩溃,所以需要先添加kotlin-reflection库。
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
下面是您可以使用 KClass 做什么的示例。
@Deprecated("已遗弃")
class Dididi {
var field1 = ""
var field2 = 0
fun function1() {}
fun function2() {}
}
// 测试方法
fun kClassTest() {
val receiverA = Dididi()
val kClass = Dididi::class
// Class 元数据
LogUtils.v(TAG, kClass.simpleName!!)
LogUtils.v(TAG, kClass.isData)
LogUtils.v(TAG, kClass.isAbstract)
LogUtils.v(TAG, kClass.isCompanion)
LogUtils.v(TAG, kClass.isFinal)
LogUtils.v(TAG, kClass.isInner)
LogUtils.v(TAG, kClass.isOpen)
LogUtils.v(TAG, kClass.isSealed)
// 创建实例
LogUtils.v(TAG, kClass.createInstance())
// 构造函数
LogUtils.v(TAG, kClass.constructors.map { it.name })
LogUtils.v(TAG, kClass.constructors.map { it.parameters })
LogUtils.v(TAG, kClass.constructors.map { it.call() })
// 注解
LogUtils.v(TAG, kClass.annotations.map { it.annotationClass.simpleName })
// 字段
val kProperty = kClass.memberProperties.find { it.name == "field1" }
(kProperty as KMutableProperty<String>).setter.call(receiverA, "Changed Field1 Value")
LogUtils.v(TAG, receiverA.field1)
// 方法
LogUtils.v(TAG, kClass.memberFunctions.map { it.name })
LogUtils.v(TAG, kClass.memberFunctions.find { it.name == "function1" }?.call(receiverA) ?: "")
}
结果如下。
A
false
false
false
true
false
false
false
com.example.Test$A@dbc59aa
[<init>]
[[]]
[com.example.Test$A@299b]
[Deprecated]
Changed Field1 Value
[function1, function2, equals, hashCode, toString]
kotlin.Unit