在 Kotlin 中,GSON.fromJson(...) 如何改变现有对象的只读字段?
In Kotlin, how does GSON.fromJson(...) manage to mutate a read-only field of an existing object?
在 Kotlin 中,如何修改实例的只读 val
字段?
在下面的 Kotlin 代码中,gson.fromJson(...)
从 InstanceCreator
得到一个 Thing(0)
并以某种方式设法将 value
从 0
突变为 1
,然后 return 该对象。怎么样?
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
}
我验证了由 gson.fromJson(...)
编辑的对象 return 与 InstanceCreator
提供的对象相同,因此它不会根据 InstanceCreator
提供的对象创建新实例=15=].
我也试过用反射设置value
,但是没有找到方法。 val
字段中没有可用的 setter。
I also tried setting value using reflection
嗯,如果你使用 Java 的反射 API,而不是 Kotlin 的反射,你就可以做到。
Kotlin val
属性转换为只有 public getter 的私有 Java 字段。您可以使用反射设置私有字段。例如:
val x = Thing(10)
val valueField = x.javaClass.getDeclaredField("value")
valueField.trySetAccessible()
valueField.setInt(x, 20)
println(x.value)
这可能也是 Gson 在幕后所做的。
在 Kotlin 中,如何修改实例的只读 val
字段?
在下面的 Kotlin 代码中,gson.fromJson(...)
从 InstanceCreator
得到一个 Thing(0)
并以某种方式设法将 value
从 0
突变为 1
,然后 return 该对象。怎么样?
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
}
我验证了由 gson.fromJson(...)
编辑的对象 return 与 InstanceCreator
提供的对象相同,因此它不会根据 InstanceCreator
提供的对象创建新实例=15=].
我也试过用反射设置value
,但是没有找到方法。 val
字段中没有可用的 setter。
I also tried setting value using reflection
嗯,如果你使用 Java 的反射 API,而不是 Kotlin 的反射,你就可以做到。
Kotlin val
属性转换为只有 public getter 的私有 Java 字段。您可以使用反射设置私有字段。例如:
val x = Thing(10)
val valueField = x.javaClass.getDeclaredField("value")
valueField.trySetAccessible()
valueField.setInt(x, 20)
println(x.value)
这可能也是 Gson 在幕后所做的。