Kotlin实现动态代理报错:java.lang.IllegalArgumentException: wrong number of arguments

本文探讨了在使用Kotlin实现JDK动态代理时遇到的wrongnumberofarguments错误,并提供了详细的解决方案。文章解释了Java与Kotlin在处理可变参数方面的差异,以及如何正确地将Kotlin数组参数传递给Java的可变参数方法。

在使用Kotlin实现JDK动态代理时遇到一个报错提示:

java.lang.IllegalArgumentException: wrong number of arguments

StackOverflow:Why is Kotlin throw IllegalArgumentException when using Proxy
简化的例子:

    var handler = object : InvocationHandler {
        val worker = Worker()
        override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
   		===== 报错位置=====》  return method!!.invoke(worker,args)
        }
    }
报错分析

在Java中实现动态代理的一个核心接口类是 java.lang.reflect.InvocationHandler,如下:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

被代理的接口对象的方法,均会在invoke中,通过被调用执行。

method.invoke(obj,args)

//Method #invoke的方法定义
public Object invoke(Object obj, Object... args)

这里需要关注的是Object[] args、Object… args这两种形式。
额外信息:

可变参数是兼容数组类参数的,但是数组类参数却无法兼容可变参数。
可变参数类型必须作为参数列表的最后一项,而不能放在定长参数的前面。

注意在Kotlin里的默认形式为:

    var handler= object :InvocationHandler{
        override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
            TODO("not implemented") 
        }
    }

这里的args:Array? , 与不定长参数是不兼容的。需要在args前加上伸展操作符(*),表示将已有的数组内容传递给函数
官方文档:可变数量的参数Varargs

修正后的写法:

method!!.invoke(worker, *(args ?: arrayOfNulls<Any>(0)))
### Java运行时出现的IllegalArgumentException异常分析 在Java运行时遇到`java.lang.IllegalArgumentException: Unknown Kotlin JVM target 21`,通常是因为Kotlin编译器无法识别指定的JVM目标版本。Kotlin的JVM目标版本是指定编译后的字节码与哪个版本的JVM兼容。如果指定了一个不支持或尚未发布的版本(如21),就会抛出此异常[^1]。 #### 异常的根本原因 该异常的根本原因是Kotlin编译器或构建工具(如Gradle或Maven)配置了错误的JVM目标版本。Kotlin目前支持的JVM目标版本包括8、9、10、11、12、13、14、15、16、17等,但尚未支持21这个版本。这可能是由于开发者误配置或使用了预发布版本的JDK导致的[^2]。 #### 解决方案 可以通过以下方法解决该问题: 1. **检查Kotlin编译器的目标版本配置** 在Gradle中,确保`kotlinOptions.jvmTarget`设置为当前支持的版本,例如17: ```gradle kotlinOptions { jvmTarget = "17" } ``` 2. **更新Kotlin插件和Gradle版本** 确保使用的Kotlin插件和Gradle版本是最新的,以支持最新的JVM目标版本。例如,在`build.gradle.kts`中添加以下内容: ```kotlin plugins { kotlin("jvm") version "1.8.20" } ``` 3. **验证JDK版本** 确保项目使用的JDK版本与配置的JVM目标版本一致。例如,如果`jvmTarget`设置为17,则需要安装并使用JDK 17。 4. **移除未知的目标版本配置** 如果项目中存在硬编码的目标版本21,应将其替换为受支持的版本。例如,在代码或配置文件中查找类似以下的内容并进行修改: ```kotlin jvmTarget = "21" // 替换为 "17" ``` #### 示例代码:Gradle配置调整 以下是调整Gradle配置的一个示例: ```gradle plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.20' } repositories { mavenCentral() } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib" } tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { jvmTarget = "17" // 设置为支持的版本 } } ``` ### 注意事项 - 如果项目需要使用未来的JVM版本(如21),需等待Kotlin官方发布对新版本的支持。 - 确保所有团队成员使用相同的JDK和构建工具版本,以避免类似的兼容性问题[^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值