In Kotlin,the code in an object expression can access variables from the scope that contains it, just like the following code:
fun countClicks(window: JCompo
In Java, you can only capture (effectively) final variables in anonymous classes and lambdas. In Kotlin, you can capture any variable, even if they are mutable.
This is done by wrapping any captured variables in instances of simple wrapper classes. These wrappers just have a single field that contains the captured variables. Since the instances of the wrappers can be final
, they can be captured as usual.
So when you do this:
var counter = 0
{ counter++ }() // definition and immediate invocation, very JavaScript
Something like this happens under the hood:
class Ref(var value: T) // generic wrapper class somewhere in the runtime
val counter = Ref(0); // wraps an Int of value 0
{ counter.value++ }() // captures counter and increments its stored value
The actual implementation of the wrapper class is written in Java, and looks like this:
public static final class ObjectRef implements Serializable {
public T element;
@Override
public String toString() {
return String.valueOf(element);
}
}
There are also additional wrappers called ByteRef
, ShortRef
, etc. that wrap the various primitives so that they don't have to be boxed in order to be captured. You can find all the wrapper classes in this file.
Credits go to the Kotlin in Action book which contains the basics of this information, and the example used here.