You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过反射访问Kotlin中的扩展函数与属性?

为什么Kotlin反射无法获取扩展函数/属性?怎么解决?

一、先解决依赖问题:缺少kotlin-reflect.jar

你提到在Kotlin Playground里无法运行,是因为kotlin.reflect.full包下的API属于kotlin-reflect扩展库,并非Kotlin标准库默认包含的内容,必须手动引入依赖:

  • 如果用Gradle构建项目,在build.gradle.kts中添加:
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.20") // 版本需和你的Kotlin版本保持一致
    
  • 如果是在Kotlin Playground中运行,可以在代码开头添加依赖注解:
    @file:DependsOn("org.jetbrains.kotlin:kotlin-reflect:1.9.20")
    

二、核心问题:扩展函数/属性的本质

你用a::class去查找扩展是找不到的,因为Kotlin的扩展并不是真的把函数/属性植入目标类中,它只是语法层面的糖衣:

  • 扩展函数会被编译成静态方法,把目标类的实例作为第一个参数传入(比如fun A.ext()编译后是static int ext(A $this)
  • 扩展属性会编译成静态的getter(如果是var类型还会有setter),同样接收目标实例作为参数
    这些静态方法都属于定义扩展的文件生成的Kt类(比如你在Main.kt里写的扩展,会生成MainKt类),和A类本身没有隶属关系。

三、正确的反射方式

要获取扩展函数/属性,你需要从定义它们的文件类KClass对象去查找,而非目标类AKClass

完整可运行示例代码

@file:DependsOn("org.jetbrains.kotlin:kotlin-reflect:1.9.20")
import kotlin.reflect.full.*

class A

// 定义扩展函数和属性
fun A.ext() = 2
val A.value: Int get() = 2

fun main() {
    val a = A()

    // ❌ 错误方式:从A类查找,找不到扩展
    val aClass = a::class
    println("A类的members: ${aClass.members.joinToString()}") // 仅输出Object自带的方法(equals、hashCode等)

    // ✅ 正确方式:从扩展所在的文件类查找
    // 通过扩展函数的引用获取其所在的文件类
    val fileClass = ::ext::class.java.enclosingClass.kotlin
    
    // 获取所有扩展函数
    val extFunctions = fileClass.memberExtensionFunctions.joinToString(", ") { it.name }
    println("扩展函数:$extFunctions") // 输出 "ext"

    // 获取所有扩展属性
    val extProperties = fileClass.memberExtensionProperties.joinToString(", ") { it.name }
    println("扩展属性:$extProperties") // 输出 "value"

    // 调用扩展函数/属性
    val extFunc = fileClass.memberExtensionFunctions.first { it.name == "ext" }
    println("调用ext()结果:${extFunc.call(a)}") // 输出2

    val valueProp = fileClass.memberExtensionProperties.first { it.name == "value" }
    println("获取value属性结果:${valueProp.get(a)}") // 输出2
}

补充说明

如果你的扩展定义在某个特定包下,也可以通过包名直接定位到文件类:

// 假设扩展在com.example包的Utils.kt文件中
val fileClass = Class.forName("com.example.UtilsKt").kotlin

内容的提问来源于stack exchange,提问作者Victor Ermolaev

火山引擎 最新活动