当前位置: 首页 > 知识库问答 >
问题:

在Kotlin中,gson.fromjson(…)是如何设法修改现有对象的只读字段的?

党浩阔
2023-03-14

在Kotlin中,如何更改实例的只读val字段?

在下面的Kotlin代码中,gson.fromjson(...)InstanceCreator获取一个东西(0)并设法将value0突变为1,然后返回该对象。怎么做?

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(...)返回的对象与InstanceCreator提供的对象相同,因此它没有基于InstanceCreator提供的对象创建新实例。

我还尝试使用反射设置value,但没有找到方法。val字段上没有可用的setter。

共有1个答案

田琛
2023-03-14

我还尝试使用反射设置值

好吧,如果你使用Java的反射API,而不是Kotlin的,你就可以做到这一点。

Kotlinval属性转换为一个只有公共getter的私有Java字段。您可以使用Reflection设置private字段。例如:

val x = Thing(10)
val valueField = x.javaClass.getDeclaredField("value")
valueField.trySetAccessible()
valueField.setInt(x, 20)
println(x.value)

这很可能也是Gson在引擎盖下所做的事情。

 类似资料:
  • 我有一个类包含如下所示同伴对象。 我想在运行时修改同伴对象的属性。我将在这个类中添加数百个属性。所以我要做动态。我使用了这个方法,得到如下错误。

  • 问题内容: 假设我们有一个对象类型,从而产生。 现在,我们要创建一个新的对象,这只是(即场和来自被修剪)。所以我们定义一个类如下: 然后我们初始化如下: 。 不幸的是,执行此操作时出现运行时错误。 问题: 我们如何如上所述定义? 问题答案: 假设你有三个字段中 创建一个新的字段 声明一个方法是这样 从A设置B的必填字段。 例如 设置f1并返回B对象 .B将成为一个成员,你可以简单地从A取得乙。 f

  • 假设我有一个项集合,例如,我需要检查是否有任何项从包装类中被修改,例如,任何项的属性的值通过setter被更改: 或者另一个问题,选择的答案建议使用标记,每次修改属性时都需要升起该标记。然而,我的类实际上会变得更脏,矛盾的是,我需要修改几十个修改Item属性的方法。 有没有其他方法,最好是透明的?

  • 问题内容: 想象一下我有这堂课: 现在,我有另一个使用上述类的类: 这就是问题所在:我已经从外部访问了班级的私有领域!我该如何预防?我的意思是如何使该数组不可变?这是否意味着您可以使用每种获取方法来逐步访问私有字段?(我不需要像Guava这样的任何库。我只需要知道执行此操作的正确方法)。 问题答案: 您必须返回阵列的 副本 。

  • 问题内容: 如果将对象引用传递给方法,是否可以将对象“只读”到该方法? 问题答案: 不严格地说。即,不能将对象突变的引用不能转换为不能对象的引用。另外,除了使用约定外,没有其他方法可以表示类型是不可变的或可变的。 确保某种形式的不变性的唯一功能就是字段-一旦写入,就不能修改。 也就是说,有一些方法可以设计类,从而 防止不必要的变异 。这里有一些技巧: 防御复制 。传递对象的副本,这样,如果该对象被

  • 问题内容: 我正在尝试遍历: …并提取中的每个元素。这是我的方法: 这里的问题是对的每次调用都会从中删除元素,从而修改其大小,从而导致以下错误: 那么…当元素动态变化时,我该如何遍历其中的元素呢? 问题答案: 其他人则提到了正确的解决方案,而没有实际阐明。所以这里是: 另外,如果您想安全地在assign函数中更改映射,则需要传入迭代器(只能使用remove函数,并且只能使用一次)或条目来更改值。