Koltin的动态代理的坑。
1.Kotlin中动态代理的实现。
class DynamicProxy constructor(any: Any): InvocationHandler{
private val mAny: Any = any
@Throws(Throwable::class)
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
return method!!.invoke(mAny,args)
}
}
2.运行报错信息:
Caused by: java.lang.IllegalArgumentException: method ....xxx argument 1 has type java.lang.String, got java.lang.Object[]
3.原因:
(1)在invoke方法中接收可变长参数,在Kotlin语法中,数组是array,可变长参数类型是vararg,类型不匹配。
(2)Kotlin中数组转为可变长参数,通过前面加*符号。
(3)如果方法没有任何参数,args将为null,并将其传播到Kotlin将导致NullPointerException.作为一种解决方法,使用*(args?:arrayOfNulls< Any>(0)),并在所描述的极端情况下选择正确的部分并将其扩展为零参数.「参考文档」
4.修改后的Koltin动态代理实现
class DynamicProxy constructor(any: Any): InvocationHandler{
private val mAny: Any = any
@Throws(Throwable::class)
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
// return method!!.invoke(mAny,args)
return method!!.invoke(mAny,*(args ?: emptyArray()))
}
}
经过以上的修改,你以为就可以了。错!!!!kotlin还有另外一个坑。
5.错误日志:
运行上面的修改后的代码。出现以下错误提示:
Caused by: java.lang.IllegalStateException: method!!.invoke(mAny,*(args ?: emptyArray())) must not be null
6.原因
(1)同样是类型不匹配导致,invoke的方法可能是没有返回值的,所以需要将any类型变成any?类型。
(2)在kotlin中存在类型和子类型两种概念,比如any和any?类型。比如在任何使用any?的地方,都可以传入any类型的变量,但是反过来却不可以。
7.完整实现逻辑:
class DynamicProxy constructor(any: Any): InvocationHandler{
private val mAny: Any = any
@Throws(Throwable::class)
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
// return method!!.invoke(mAny,args)
return method!!.invoke(mAny,*(args ?: emptyArray()))
}
}
8.参考文章:
Kotlin动态代理的实现出现的Exception
网友评论