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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章