Kotlin反射与元编程:动态编程的魔法
/ 反射基础println("类名:${import kotlin . reflect . KClass import kotlin . reflect . full . memberProperties import kotlin . reflect . full . primaryConstructor // 反射基础 fun main() {
·
💡 导读:反射是Kotlin最强大的特性之一,它让我们能够在运行时检查和操作类型信息。本文将带你深入探索Kotlin反射的世界,掌握动态编程的魔法!
📋 目录
📚 反射基础
反射概述
import kotlin.reflect.KClass
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
// 反射基础
fun main() {
val stringClass: KClass<String> = String::class
println("类名: ${stringClass.simpleName}")
println("完整类名: ${stringClass.qualifiedName}")
println("是否为数据类: ${stringClass.isData}")
println("是否为密封类: ${stringClass.isSealed}")
}
获取类引用
// 获取类引用的不同方式
fun main() {
// 1. 使用::class
val stringClass = String::class
val intClass = Int::class
// 2. 使用::class.java
val stringJavaClass = String::class.java
val intJavaClass = Int::class.java
// 3. 从对象获取
val obj = "Hello"
val objClass = obj::class
println("String类: $stringClass")
println("Int类: $intClass")
println("对象类: $objClass")
}
🏗️ 类反射
类信息检查
import kotlin.reflect.full.*
data class Person(
val name: String,
val age: Int,
val email: String
)
fun main() {
val personClass = Person::class
// 检查类特性
println("是否为数据类: ${personClass.isData}")
println("是否为抽象类: ${personClass.isAbstract}")
println("是否为密封类: ${personClass.isSealed}")
println("是否为接口: ${personClass.isInterface}")
// 获取构造函数
val primaryConstructor = personClass.primaryConstructor
println("主构造函数: $primaryConstructor")
// 获取所有构造函数
val constructors = personClass.constructors
println("所有构造函数: $constructors")
}
成员检查
import kotlin.reflect.full.*
class ExampleClass {
val property1: String = "Hello"
var property2: Int = 42
private val privateProperty: Boolean = true
fun publicFunction() = "Public"
private fun privateFunction() = "Private"
}
fun main() {
val exampleClass = ExampleClass::class
// 获取所有属性
val properties = exampleClass.memberProperties
println("所有属性:")
properties.forEach { prop ->
println(" ${prop.name}: ${prop.returnType}")
}
// 获取所有函数
val functions = exampleClass.memberFunctions
println("所有函数:")
functions.forEach { func ->
println(" ${func.name}: ${func.parameters.size} 参数")
}
// 获取所有成员
val members = exampleClass.members
println("所有成员数量: ${members.size}")
}
⚡ 函数反射
函数引用
// 函数引用
fun add(a: Int, b: Int): Int = a + b
fun multiply(a: Int, b: Int): Int = a * b
fun main() {
// 获取函数引用
val addFunction = ::add
val multiplyFunction = ::multiply
// 调用函数
println("加法: ${addFunction(5, 3)}")
println("乘法: ${multiplyFunction(5, 3)}")
// 获取函数信息
println("函数名: ${addFunction.name}")
println("参数数量: ${addFunction.parameters.size}")
println("返回类型: ${addFunction.returnType}")
}
函数反射操作
import kotlin.reflect.full.*
class Calculator {
fun add(a: Int, b: Int): Int = a + b
fun subtract(a: Int, b: Int): Int = a - b
fun multiply(a: Int, b: Int): Int = a * b
fun divide(a: Int, b: Int): Double = a.toDouble() / b
}
fun main() {
val calculator = Calculator()
val calculatorClass = Calculator::class
// 获取所有函数
val functions = calculatorClass.memberFunctions
// 动态调用函数
functions.forEach { function ->
if (function.name != "equals" && function.name != "hashCode" && function.name != "toString") {
try {
val result = function.call(calculator, 10, 5)
println("${function.name}(10, 5) = $result")
} catch (e: Exception) {
println("调用 ${function.name} 失败: ${e.message}")
}
}
}
}
🎯 属性反射
属性访问
import kotlin.reflect.full.*
data class User(
val id: Int,
var name: String,
var email: String,
private val secretKey: String = "secret"
)
fun main() {
val user = User(1, "张三", "zhangsan@example.com")
val userClass = User::class
// 获取所有属性
val properties = userClass.memberProperties
properties.forEach { property ->
try {
val value = property.get(user)
println("${property.name}: $value")
} catch (e: Exception) {
println("无法访问 ${property.name}: ${e.message}")
}
}
}
属性修改
import kotlin.reflect.full.*
class Config {
var host: String = "localhost"
var port: Int = 8080
var timeout: Int = 30000
}
fun main() {
val config = Config()
val configClass = Config::class
// 获取可变属性
val mutableProperties = configClass.memberProperties.filter { it is KMutableProperty }
// 动态设置属性
mutableProperties.forEach { property ->
when (property.name) {
"host" -> (property as KMutableProperty<*>).setter.call(config, "api.example.com")
"port" -> (property as KMutableProperty<*>).setter.call(config, 443)
"timeout" -> (property as KMutableProperty<*>).setter.call(config, 60000)
}
}
println("配置更新后:")
println("host: ${config.host}")
println("port: ${config.port}")
println("timeout: ${config.timeout}")
}
🏷️ 注解反射
注解检查
import kotlin.reflect.full.*
// 自定义注解
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiEndpoint(val path: String)
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Required
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Deprecated(val reason: String)
// 使用注解的类
@ApiEndpoint("/api/users")
class UserController {
@Required
var userId: String = ""
@Deprecated("使用新的getUserById方法")
fun getUser(id: String): String = "User: $id"
fun getUserById(id: String): String = "User: $id"
}
fun main() {
val userControllerClass = UserController::class
// 检查类注解
val classAnnotation = userControllerClass.findAnnotation<ApiEndpoint>()
if (classAnnotation != null) {
println("API端点: ${classAnnotation.path}")
}
// 检查属性注解
userControllerClass.memberProperties.forEach { property ->
val requiredAnnotation = property.findAnnotation<Required>()
if (requiredAnnotation != null) {
println("必需属性: ${property.name}")
}
}
// 检查函数注解
userControllerClass.memberFunctions.forEach { function ->
val deprecatedAnnotation = function.findAnnotation<Deprecated>()
if (deprecatedAnnotation != null) {
println("已弃用函数: ${function.name}, 原因: ${deprecatedAnnotation.reason}")
}
}
}
注解处理器
import kotlin.reflect.full.*
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Validatable
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Min(val value: Int)
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Max(val value: Int)
@Validatable
data class Product(
@Min(1) val id: Int,
@Min(1) @Max(100) val price: Double,
val name: String
)
class Validator {
fun validate(obj: Any): List<String> {
val errors = mutableListOf<String>()
val objClass = obj::class
// 检查是否有Validatable注解
if (!objClass.hasAnnotation<Validatable>()) {
return errors
}
// 验证属性
objClass.memberProperties.forEach { property ->
val minAnnotation = property.findAnnotation<Min>()
val maxAnnotation = property.findAnnotation<Max>()
val value = property.get(obj)
if (minAnnotation != null && value is Number) {
if (value.toDouble() < minAnnotation.value) {
errors.add("${property.name} 不能小于 ${minAnnotation.value}")
}
}
if (maxAnnotation != null && value is Number) {
if (value.toDouble() > maxAnnotation.value) {
errors.add("${property.name} 不能大于 ${maxAnnotation.value}")
}
}
}
return errors
}
}
fun main() {
val validator = Validator()
val validProduct = Product(1, 50.0, "手机")
val invalidProduct = Product(0, 150.0, "电脑")
println("验证有效产品:")
val validErrors = validator.validate(validProduct)
if (validErrors.isEmpty()) {
println("验证通过")
} else {
validErrors.forEach { println("错误: $it") }
}
println("验证无效产品:")
val invalidErrors = validator.validate(invalidProduct)
invalidErrors.forEach { println("错误: $it") }
}
🎯 实战应用
1. 动态对象创建
import kotlin.reflect.full.*
class ObjectFactory {
fun <T : Any> createInstance(clazz: KClass<T>): T? {
return try {
clazz.primaryConstructor?.call()
} catch (e: Exception) {
println("创建实例失败: ${e.message}")
null
}
}
fun <T : Any> createInstanceWithParams(
clazz: KClass<T>,
vararg params: Any
): T? {
return try {
clazz.primaryConstructor?.call(*params)
} catch (e: Exception) {
println("创建实例失败: ${e.message}")
null
}
}
}
data class Person(val name: String, val age: Int)
class SimpleClass
fun main() {
val factory = ObjectFactory()
// 创建无参实例
val simpleInstance = factory.createInstance(SimpleClass::class)
println("简单类实例: $simpleInstance")
// 创建带参数实例
val personInstance = factory.createInstanceWithParams(
Person::class,
"张三",
25
)
println("人员实例: $personInstance")
}
2. 配置加载器
import kotlin.reflect.full.*
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class ConfigProperty(val key: String)
class AppConfig {
@ConfigProperty("app.name")
var appName: String = ""
@ConfigProperty("app.version")
var appVersion: String = ""
@ConfigProperty("database.url")
var databaseUrl: String = ""
@ConfigProperty("database.port")
var databasePort: Int = 0
}
class ConfigLoader {
fun loadConfig(configClass: KClass<*>, properties: Map<String, String>): Any {
val instance = configClass.primaryConstructor?.call() ?: return Any()
configClass.memberProperties.forEach { property ->
val annotation = property.findAnnotation<ConfigProperty>()
if (annotation != null) {
val value = properties[annotation.key]
if (value != null) {
try {
when (property.returnType.classifier) {
String::class -> (property as KMutableProperty<*>).setter.call(instance, value)
Int::class -> (property as KMutableProperty<*>).setter.call(instance, value.toInt())
Boolean::class -> (property as KMutableProperty<*>).setter.call(instance, value.toBoolean())
}
} catch (e: Exception) {
println("设置属性 ${property.name} 失败: ${e.message}")
}
}
}
}
return instance
}
}
fun main() {
val properties = mapOf(
"app.name" to "MyApp",
"app.version" to "1.0.0",
"database.url" to "localhost",
"database.port" to "5432"
)
val loader = ConfigLoader()
val config = loader.loadConfig(AppConfig::class, properties) as AppConfig
println("应用名称: ${config.appName}")
println("应用版本: ${config.appVersion}")
println("数据库URL: ${config.databaseUrl}")
println("数据库端口: ${config.databasePort}")
}
3. 序列化器
import kotlin.reflect.full.*
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Serialize
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class Ignore
class JsonSerializer {
fun serialize(obj: Any): String {
val objClass = obj::class
val properties = objClass.memberProperties.filter {
it.hasAnnotation<Serialize>() && !it.hasAnnotation<Ignore>()
}
val jsonParts = properties.map { property ->
val value = property.get(obj)
"\"${property.name}\": ${serializeValue(value)}"
}
return "{${jsonParts.joinToString(", ")}}"
}
private fun serializeValue(value: Any?): String {
return when (value) {
null -> "null"
is String -> "\"$value\""
is Number, is Boolean -> value.toString()
else -> "\"$value\""
}
}
}
@Serialize
data class User(
@Serialize val id: Int,
@Serialize val name: String,
@Serialize @Ignore val password: String,
@Serialize val email: String
)
fun main() {
val user = User(1, "张三", "secret123", "zhangsan@example.com")
val serializer = JsonSerializer()
val json = serializer.serialize(user)
println("JSON: $json")
}
📊 性能考虑
反射性能
import kotlin.reflect.full.*
// 缓存反射信息以提高性能
class ReflectionCache {
private val classCache = mutableMapOf<KClass<*>, ClassInfo>()
data class ClassInfo(
val properties: List<KProperty1<*, *>>,
val functions: List<KFunction<*>>,
val annotations: List<Annotation>
)
fun getClassInfo(clazz: KClass<*>): ClassInfo {
return classCache.getOrPut(clazz) {
ClassInfo(
properties = clazz.memberProperties,
functions = clazz.memberFunctions,
annotations = clazz.annotations
)
}
}
}
// 使用缓存
fun main() {
val cache = ReflectionCache()
val userClass = User::class
// 第一次获取(会缓存)
val info1 = cache.getClassInfo(userClass)
// 第二次获取(从缓存)
val info2 = cache.getClassInfo(userClass)
println("属性数量: ${info1.properties.size}")
println("函数数量: ${info1.functions.size}")
}
🎯 总结与进阶
今日收获
通过本篇文章,你已经掌握了:
- 反射基础 - 反射的概念和基本使用
- 类反射 - 类信息检查和成员访问
- 函数反射 - 函数引用和动态调用
- 属性反射 - 属性访问和修改
- 注解反射 - 注解检查和处理器
- 实战应用 - 动态对象创建、配置加载、序列化
🚀 进阶学习方向
- 反射与泛型 - 泛型类型信息
- 反射与协程 - 异步反射操作
- 反射DSL - 动态DSL构建
- 反射性能优化 - 高级性能技巧
💡 最佳实践
- 谨慎使用反射 - 反射有性能开销
- 缓存反射信息 - 避免重复计算
- 异常处理 - 反射操作可能失败
- 类型安全 - 注意类型转换安全
📚 推荐资源
🌟 下期预告:我们将探索Kotlin的DSL世界,学习领域特定语言构建,掌握声明式编程的艺术。敬请期待!
📝 作者寄语:反射是动态编程的魔法,它让我们能够在运行时探索和操作类型信息。让我们一起在反射的世界里创造更多可能!
🔗 相关文章:
如果这篇文章对你有帮助,请点赞、收藏、关注,你的支持是我创作的动力! 🚀
更多推荐
所有评论(0)