💡 导读:反射是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}")
}

🎯 总结与进阶

今日收获

通过本篇文章,你已经掌握了:

  1. 反射基础 - 反射的概念和基本使用
  2. 类反射 - 类信息检查和成员访问
  3. 函数反射 - 函数引用和动态调用
  4. 属性反射 - 属性访问和修改
  5. 注解反射 - 注解检查和处理器
  6. 实战应用 - 动态对象创建、配置加载、序列化

🚀 进阶学习方向

  1. 反射与泛型 - 泛型类型信息
  2. 反射与协程 - 异步反射操作
  3. 反射DSL - 动态DSL构建
  4. 反射性能优化 - 高级性能技巧

💡 最佳实践

  1. 谨慎使用反射 - 反射有性能开销
  2. 缓存反射信息 - 避免重复计算
  3. 异常处理 - 反射操作可能失败
  4. 类型安全 - 注意类型转换安全

📚 推荐资源


🌟 下期预告:我们将探索Kotlin的DSL世界,学习领域特定语言构建,掌握声明式编程的艺术。敬请期待!


📝 作者寄语:反射是动态编程的魔法,它让我们能够在运行时探索和操作类型信息。让我们一起在反射的世界里创造更多可能!

🔗 相关文章


如果这篇文章对你有帮助,请点赞、收藏、关注,你的支持是我创作的动力! 🚀

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐