1

Say I have a function haveFun which takes in a Method (from java.lang.reflect package) as a param and returns a lambda as below

typealias AnyFun = (o: Any?) -> Any?

fun haveFun(method: Method): AnyFun {
    return { o -> method.invoke(o) }
}

data class Game(val name: String)

Now if I pass a method to the function and assign the lambda to a field as

val game = haveFun(Game::name.javaGetter!!)

Can I find out and access the Method that was passed to the function using the above game field which is a lambda?

I can see the Method while debugging on Intellij, but not sure on how to access it.

enter image description here

Madhu Bhat
  • 13,559
  • 2
  • 38
  • 54

1 Answers1

2

You can access and use it through reflection as a declaredField having $method name, as follows:

val methodField = game.javaClass.getDeclaredField("\$method")
val method = methodField.get(game) as Method
println(method.invoke(Game("Pietro"))) // outputs the String "Pietro"
Pietro Martinelli
  • 1,776
  • 14
  • 16
  • 2
    Some explanation: The value of `game` in Java is essentially an anonymous class that captures a reference to `method`, so `method` should be one of the fields of the anonymous class, except it is implicit so its name is `$method`. – Tenfour04 Jan 14 '20 at 17:29
  • Thanks for your answer @PietroMartinelli. I needed to know if reflection is the only way out for this? – Madhu Bhat Jan 16 '20 at 06:33
  • Thanks for the explanation @Tenfour04. So reflection is the only way to get the method field? The caveat would be if the `method` field's name is refactored, then the code with getting the field with `$method` would not work. – Madhu Bhat Jan 16 '20 at 06:36
  • 1
    You could use `getDeclaredFields().first()!!`. Since you know there’s exactly one, this is safe, but if you change the number of arguments you could be in trouble. – Tenfour04 Jan 16 '20 at 12:03