Koltin 之 动态代理InvocationHandler

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?): 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?): 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?): Any? {
//        return method!!.invoke(mAny,args)
        return method!!.invoke(mAny,*(args ?: emptyArray()))
    }
}

8.参考文章:
Kotlin动态代理的实现出现的Exception

你可能感兴趣的:(Kotlin)