Koltin 之 动态代理InvocationHandler

Posted android小菜比

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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<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

以上是关于Koltin 之 动态代理InvocationHandler的主要内容,如果未能解决你的问题,请参考以下文章

Koltin实现动态心率曲线

Kotlin易踩坑之委托的使用

Kotlin易踩坑之委托的使用

Kotlin易踩坑之委托的使用

设计模式之动态代理

代理模式之JDK动态代理