In Kotlin, how can an instance’s read-only val
field be mutated?
In the following Kotlin code, gson.fromJson(...)
gets a Thing(0)
from the InstanceCreator
and somehow manages to mutate value
from 0
to 1
, then return that object. How?
import com.google.gson.GsonBuilder import com.google.gson.InstanceCreator class Thing(val value: Int) fun main() { val creator = InstanceCreator { Thing(0) } val gson = GsonBuilder().registerTypeAdapter(Thing::class.java, creator).create() val thing = gson.fromJson("""{"value":1}""", Thing::class.java) println(thing.value) // 1 }
I verified that the object returned by gson.fromJson(...)
is the same object provided by the InstanceCreator
, so it’s not creating a new instance based on the one provided by the InstanceCreator
.
I also tried setting value
using reflection, but didn’t find a way. There was no setter available on the val
field.
Advertisement
Answer
I also tried setting value using reflection
Well, you can do it if you use Java’s reflection API, rather than Kotlin’s.
Kotlin val
properties translates to a private Java field with only a public getter. You can set the private field using reflection. For example:
val x = Thing(10) val valueField = x.javaClass.getDeclaredField("value") valueField.trySetAccessible() valueField.setInt(x, 20) println(x.value)
This is probably also what Gson does under the hood.