Why is Kotlin throw IllegalArgumentException when using Proxy

后端 未结 1 432
眼角桃花
眼角桃花 2021-01-20 16:07

This is the Kotlin equivalent of Java code using InvocationHandler:

override fun invoke(proxy: Any?, method: Method?, args: Array         


        
相关标签:
1条回答
  • 2021-01-20 16:38

    When you pass args into method!!.invoke(obj, args) in Kotlin, it is actually a single argument of array type, and by default it is not decomposed into its elements as separate arguments.

    To achieve that behavior instead, use the spread operator: *args

    val ret = method!!.invoke(obj, *args)
    

    With this syntax, args will be passed in the same way as in Java varargs. For example, these lines of code are equivalent:

    someVarargsFunction("a", "b", "c", "d", "e")
    someVarargsFunction("a", "b", *arrayOf("c", "d"), "e")
    

    Note: if a method doesn't have any parameters, args will be null, and spreading it in Kotlin would result into a NullPointerException. As a workaround, use *(args ?: arrayOfNulls<Any>(0)), and in the described corner case the right part is chosen and spread into zero arguments.


    My example proxy implementation:

    interface SomeInterface {
        fun f(a: Int, b: Int): Int
    }
    
    val obj = object : SomeInterface {
        override fun f(a: Int, b: Int) = a + b
    }
    

    val a = Proxy.newProxyInstance(
            SomeInterface::class.java.classLoader,
            arrayOf(SomeInterface::class.java)) { proxy, method, args ->
        println("Before; args: " + args?.contentToString())
        val ret = method!!.invoke(obj, *(args ?: arrayOfNulls<Any>(0)))
        println("After; result: $ret")
        ret
    } as SomeInterface
    
    println(a.f(1, 2))
    

    And the output is:

    Before; args: [1, 2]
    After; result: 3
    3
    
    0 讨论(0)
提交回复
热议问题