You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin反射调用伴生对象方法报错:参数不匹配问题求助

解决Kotlin伴生对象反射调用的参数不足异常

问题背景

用ClassGraph扫描带@OnStartup注解的Kotlin伴生对象方法,启动时调用这些方法通知中心类,结果抛出异常:

Exception in thread "main" java.lang.IllegalArgumentException: Callable expects 1 arguments, but 0 were provided

推测需要传入伴生对象实例,但不知道怎么获取。

问题原因

Kotlin伴生对象在JVM上其实是宿主类的一个内部单例类,它的方法默认是这个单例类的成员方法,而非宿主类的静态方法。所以通过kotlinFunction拿到的KFunction调用时,必须传入伴生对象的实例作为第一个参数,否则就会报参数不足。

两种解决思路

思路一:给方法加@JvmStatic注解

直接给伴生对象里的@OnStartup方法加上@JvmStatic,让它变成JVM层面的静态方法,这样调用时不需要传任何参数。

修改后的SomeClass:

data class SomeClass(val name: String) {
  companion object {
    @OnStartup
    @JvmStatic // 新增注解
    fun onStartup() {
      // 在启动时通知相关方本类的存在
    }
  }
}

原有的main和findStartupMethods代码不用改,直接运行即可。

思路二:手动获取伴生对象实例并传入

如果没法修改目标类的代码,就通过反射获取伴生对象的单例实例,调用方法时把它传进去。

修改后的核心代码:

fun main() {
  val scanResult = ClassGraph().enableAllInfo().acceptPackages("com.test").scan()

  scanResult
    .getClassesWithMethodAnnotation(OnStartup::class.java.name)
    .flatMap { getStartupMethodWithCompanion(it) }
    .forEach { (func, companionInstance) -> func.call(companionInstance) }
}

private fun getStartupMethodWithCompanion(classInfo: ClassInfo): List<Pair<KFunction<*>, Any>> {
  return classInfo.methodInfo.filter { it.hasAnnotation(OnStartup::class.java) }
    .mapNotNull { method ->
      val kFunc = method.loadClassAndGetMethod().kotlinFunction ?: return@mapNotNull null
      val hostKClass = classInfo.loadClass().kotlin
      // 获取伴生对象实例
      val companion = hostKClass.companionObjectInstance ?: return@mapNotNull null
      kFunc to companion
    }
}

这里通过hostKClass.companionObjectInstance拿到伴生对象的单例,然后作为参数传给KFunction.call()。

注意点

  • 如果伴生对象是private的,companionObjectInstance会返回null,要确保伴生对象是公共访问权限(默认就是public)。
  • 思路一适合你能修改目标类的场景,简单直接;思路二更灵活,不用动目标类,适合扫描第三方类的情况。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:51:20