How Method reference works : Kotlin

Method reference in Kotlin is one of the most talked about and loved features.
I have always wondered how method reference internally works.
Syntax is pretty straight forward. You can declare a method and pass it as shown below.
class Hello() {
fun test() {
val sum = ComplexSum()
sum.receiver(::saveInDb)
}
fun saveInDb() {
println("saving to Db")
doSomething()
}
}class ComplexSum {
fun receiver(method: () -> (Unit)) {
method()
}
}
Here are two classes Hello and complex sum.
we pass the reference of saveInDb to complex sum and it straight away executes it.
But how does that internally work??. How is method passed to ComplexSum??
Methods don’t independently exist in java world, they are dependent on classes.
To understand method reference is achieved we can check out Kotlin byte code. There is a neat tool in intellij which allows us to convert Kotlin byte code to human readable java code.
So without further ado lets find out what inside this generated code.
public final class Hello {
public final void test() {
ComplexSum sum = new ComplexSum();
sum.receiver((Function0)(new Function0((Hello)this) {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
this.invoke();
return Unit.INSTANCE;
}
public final void invoke() {
((Hello)this.receiver).saveInDb();
}
public final KDeclarationContainer getOwner() {
return Reflection.getOrCreateKotlinClass(Hello.class);
}
public final String getName() {
return "saveInDb";
}
public final String getSignature() {
return "saveInDb()V";
}
}));
}
public final void saveInDb() {
String var1 = "saving to Db";
boolean var2 = false;
System.out.println(var1);
this.doSomething();
}
}
If you see generated method test you will find an anonymous inner class of type function0 is generated . We have another function invoke.
So what is happening here?
Let’s see what is function0
public interface Function0<out R> : Function<R> {
/** Invokes the function. */
public operator fun invoke(): R
}
So function0 is in interface.
what kotlin compiler is doing is , it wraps the function in another class(Function0) and then passes the object of the class as reference to ComplexSum
public final class ComplexSum {
public final void receiver(@NotNull Function0 method) {
Intrinsics.checkParameterIsNotNull(method, "method");
method.invoke();
}
}
here we see in class ComplexSum function receiver recieves an instance of Function0 and calls invoke method.
invoke method in turn calls the orignal saveInDb method like this ((Hello)this.receiver).saveInDb();
So what does it mean. We also see reference of calling class also being passed to the generated code.
So this is how method reference internally works.
Can this cause memory leaks in context of android.
If you call pass reference of methods from activity to class which is doing heavy IO operation and activity is destroyed in while the IO operation is being performed the reference of activity will still be held by function reference which seems to me as valid case for memory leaks. But i do need to dig a little deeper thats the topic for another blog. :D