java.lang.IllegalArgumentException: Callable espera 4 arguments, pero se proporcionaron 3

Intento invocar una function usando la reflexión de Kotlin, pero obtengo el error:

java.lang.IllegalArgumentException: Callable espera 4 arguments, pero se proporcionaron 3.

Este es el código que hace la llamada reflexiva:

annotation.listeners.forEach { listener: KClass<*> -> listener.functions.forEach { function: KFunction<*> -> if (function.name == "before") { function.call(annotation.action, request, response) } } } 

Agregué types para listener y function solo para hacer la pregunta más legible.

Este es el método que se está llamando:

 fun before(action: String, request: RestRequest, response: RestResponse) 

Para verificar que mis types sean correctos, hice esto:

 if (function.name == "before") { println(annotation.action::class) println(request::class) println(response::class) } 

Esto imprime (que son los types correctos necesarios para la function before ):

 class kotlin.String class com.mycompany.RestRequest class com.mycompany.RestResponse 

¿Cuál debería ser el cuarto parámetro?

Falta el parámetro "this", que es el object con el que debe llamarse el método.

debería ser el primer argumento para el método

No es obvio directamente, pero echemos un vistazo al documento de KCallable :

 /** * Calls this callable with the specified list of arguments and returns the result. * Throws an exception if the number of specified arguments is not equal to the size of [parameters], * or if their types do not match the types of the parameters */ public fun call(vararg args: Any?): R 

"Lanza una exception si el número de arguments no es igual al tamaño de [parameters] […]". Los parameters, por otro lado, son una List<KParameter> con el siguiente DOC:

  /** * Parameters requinetworking to make a call to this callable. * If this callable requires a `this` instance or an extension receiver parameter, * they come first in the list in that order. */ public val parameters: List<KParameter> 

"Si este invocable requiere una instancia […] [it] ven [s] primero en la list en ese order".

Como bennyl ya respondió correctamente, this instancia es el primer parámetro, que viene antes que los otros tres porque el método necesita una instancia para invocarse.

Puedes verlo cuando miras el contenido de los parameter :

 class X{ fun before(action: String, request: String, response: String)= println("called") } fun main(args: Array<String>) { X::class.functions.forEach { function: KFunction<*> -> if (function.name == "before") { function.parameters.forEach{ println(it)} //function.call(X(), "a", "b", "c") } } } 

El parameter impreso parameter ve de la siguiente manera:

instancia de diversión de.swirtz.jugcdemo.prepanetworking.X.antes (kotlin.String, kotlin.String, kotlin.String): kotlin.Unit

parámetro # 1 acción de diversión de.swirtz.jugcdemo.prepanetworking.X.antes (kotlin.String, kotlin.String, kotlin.String): kotlin.Unit

parámetro # 2 request de diversión de.swirtz.jugcdemo.prepanetworking.X.antes (kotlin.String, kotlin.String, kotlin.String): kotlin.Unit

parámetro # 3 respuesta de diversión de.swirtz.jugcdemo.prepanetworking.X.antes (kotlin.String, kotlin.String, kotlin.String): kotlin.Unit

  • Determinar si una instancia es una instancia de una class de datos
  • ¿Cómo obtengo las funciones declaradas de una class Kotlin (KClass en M12)?
  • ¿Puedo get una KFunction de una variable del tipo de function en Kotlin?
  • Kotlin: ¿Es aquí una forma inteligente de lanzar NotImplementedError para todos los methods de una class?
  • Acceda al tipo de delegado de Kotlin sin una instancia
  • Obtén la function por nombre dinámicamente en Kotlin
  • La igualdad de class Kotlin falla
  • Kotlin: ¿Cómo puedo usar la reflexión en los packages?
  • ¿El comstackdor de Kotlin siempre conserva los nombres de los parameters en bytecode?
  • ¿Es seguro llamar a kclass.memberProperties en un object desconocido (Cualquiera)?
  • Kotlin invoke getter / setter reflexivamente