局部变量值传递给方法后发生更改

时间:2019-06-15 07:13:16

标签: java json pass-by-reference pass-by-value jsonnode

我正在使用com.fasterxml.jackson.databind.JsonNode Java库来解析JSON并对JSON字符串执行一些操作,如下所示-

public static void main(String[] args) {
{
    String jsonString = "{\"state\":{\"reported\":{\"deviceParams\":{\"deviceStatus\":{\"solenoid\":10,\"airFlow\":20}}}}}";

    ObjectMapper mapper = new ObjectMapper();

    JsonNode jsonNode = null;
    try {
        jsonNode = mapper.readTree(jsonString);
    } catch (IOException e) {
        e.printStackTrace();
    }

    JsonNode subNode = jsonNode.get("state").get("reported").get("deviceParams").get("deviceStatus");
    //Now subNode = {"solenoid":10,"airFlow":20}

    modifySubNode((ObjectNode) subNode);
    //type-casting JsonNode to ObjectNode since JSON manipulation like deletion and addition of nodes is only allowed in ObjectNode, not JsonNode
}

private static void modifySubNode(ObjectNode node) {
    if (node.get("solenoid") != null) {
        node.put("solenoid", 100);
    }
}

在函数调用modifySubNode()之后,我希望jsonNode的值保持为

{
  "state":
  {
    "reported":
    {
      "deviceParams":
      {
        "deviceStatus":
        {
          "solenoid": 10,
          "airFlow": 20
        }
      }
    }
  }
}

但是相反,它变成了这个

{
  "state":
  {
    "reported":
    {
      "deviceParams":
      {
        "deviceStatus":
        {
          "solenoid": 100,
          "airFlow": 20
        }
      }
    }
  }
}

为什么会这样?我认为对“ subNode”的任何更改都不应反映在“ jsonNode”上。我有误会吗?

1 个答案:

答案 0 :(得分:0)

这里:

jsonNode = mapper.readTree(deviceShadow);

这会在您的JSON数据中创建内存中表示形式。只是某种反映JSON字符串的结构和内容的数据结构。

这里:

JsonNode subNode = jsonNode.get(...

然后遍历该内存结构并标识其子结构。然后,您修改那个子结构:

node.put("solenoid", 100);

毫不奇怪:修改内存中的数据结构时,您就是在修改数据!

换句话说:您的假设完全是错误的。假设您有一些带有多个节点的标准Java Tree实现。现在,您在该树中标识特定的Node对象,并更改该Node的值。当然,这也会更改树的内容,因为该节点位于该树的内部

长话短说:您将数据读入内存,专门针对该数据的特定部分,更改数据,然后更改数据。这就是全部!

仅作记录:最后,我们在谈论底层JSON库的语义。您在此处使用的库...在您请求子节点时根本不会复制或克隆数据。它只是为您提供了指向数据的“指针”。其他库可能会做不同的事情,例如,可以想象所有数据都是只读的,并且修改是通过返回与初始数据分离的全新Node对象完成的。

为了不更改初始的 jsonNode 对象,唯一的选择似乎是解析数据两次 。因此,通过处理两次输入来创建完全独立的JsonNode。当然,这会使您的代码工作量加倍。