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