Android/Java 方法的奇怪问题。控制似乎跳过 if/else 块

发布于 2024-10-10 10:52:23 字数 3646 浏览 3 评论 0原文

在下面的 Android 示例中,我有一组 JSON 对象(称为模板),并且正在对它们进行某种继承处理。如果一个 JSON 对象有一个键“extends”,则相应的值将引用另一个 JSON 对象。我只是将引用的 JSON 对象中的映射复制到当前对象中。每个属性(在代码中称为组件)都会有子属性,因此每个子属性都是单独复制的。 所有 JSON 对象都存储在 HashMap 中。 编辑:发布演示该问题的示例代码。

package com.trial;

import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;

public class Trial extends Activity {

    HashMap<String, JSONObject> templates = new HashMap<String, JSONObject>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try {
            templates.put("entity", new JSONObject("{\"Health\":{\"health\":50,\"maxHealth\":100}}"));
            templates.put("unit", new JSONObject("{\"Health\":{\"health\":70},\"extends\":\"entity\"}"));
            Iterator<String> templatesIterator = templates.keySet().iterator();
            while (templatesIterator.hasNext()) {
                String templateName = templatesIterator.next();
                JSONObject template = templates.get(templateName); 
                if (template.has("extends"))
                    templates.put(templateName, processInheritance(template));
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private JSONObject processInheritance(JSONObject template) throws JSONException {
        if (template.has("extends")) {
            //If current template extends from another template
            String parentTemplateName = template.getString("extends");
            template.remove("extends");
            JSONObject parentTemplate = processInheritance(templates.get(parentTemplateName));
            //Create a clone of the parent to which child properties/components can be added
            JSONObject processedTemplate = new JSONObject(parentTemplate.toString());
            Iterator<String> it = template.keys();
            while (it.hasNext()) {
                String componentName = it.next();
                if (processedTemplate.has(componentName)) {
                    //Component is already present. Loop through Component properties and make
                    //specific replacements
                    JSONObject componentData = template.getJSONObject(componentName);
                    Iterator<String> it2 = componentData.keys();
                    JSONObject processedComponentData = processedTemplate.getJSONObject(componentName); 
                    while (it2.hasNext()) {
                        String propertyName = it2.next();
                        processedComponentData.put(propertyName, componentData.get(propertyName));
                    }
                    processedTemplate.put(componentName, processedComponentData);
                } else {
                    //Component is not already present. Simply copy
                    processedTemplate.put(componentName, template.get(componentName));
                }
            }
            return processedTemplate;
        } else {
            return template;
        }
    }
}

在调试时,我注意到代码在 while 循环之后执行得很好。 while 循环结束后不久,它会跳过 if/else 并返回“template”而不是“processedTemplate”。甚至结果对象也表明正在返回“模板”。我尝试清除二进制文件,重新创建模拟器,然后在实际设备上执行它。这种奇怪的行为仍然存在。有人能告诉我为什么会发生这种情况吗?

编辑:返回正确的对象。我之前评论说“模板”被返回是因为一个错误,我没有将返回的流程对象保存回 HashMap。 我只是在做

if (template.has("extends"))
    processInheritance(template));

但是控制似乎仍然跳跃。我想是 Eclipse 的问题。

In the following Android sample, I have a set of JSON objects(referred to as templates) and I'm doing a sort of inheritance processing on them. If a JSON object has a key "extends", the corresponding value will refer to another JSON object. I just copy the mappings in the referred JSON object to the current one. Each property (referred to as component in the code) will have sub properties, so each sub property is copied individually.
All the JSON objects are stored in a HashMap.
EDIT: Posting sample code which demonstrates the issue.

package com.trial;

import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;

public class Trial extends Activity {

    HashMap<String, JSONObject> templates = new HashMap<String, JSONObject>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try {
            templates.put("entity", new JSONObject("{\"Health\":{\"health\":50,\"maxHealth\":100}}"));
            templates.put("unit", new JSONObject("{\"Health\":{\"health\":70},\"extends\":\"entity\"}"));
            Iterator<String> templatesIterator = templates.keySet().iterator();
            while (templatesIterator.hasNext()) {
                String templateName = templatesIterator.next();
                JSONObject template = templates.get(templateName); 
                if (template.has("extends"))
                    templates.put(templateName, processInheritance(template));
            }
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private JSONObject processInheritance(JSONObject template) throws JSONException {
        if (template.has("extends")) {
            //If current template extends from another template
            String parentTemplateName = template.getString("extends");
            template.remove("extends");
            JSONObject parentTemplate = processInheritance(templates.get(parentTemplateName));
            //Create a clone of the parent to which child properties/components can be added
            JSONObject processedTemplate = new JSONObject(parentTemplate.toString());
            Iterator<String> it = template.keys();
            while (it.hasNext()) {
                String componentName = it.next();
                if (processedTemplate.has(componentName)) {
                    //Component is already present. Loop through Component properties and make
                    //specific replacements
                    JSONObject componentData = template.getJSONObject(componentName);
                    Iterator<String> it2 = componentData.keys();
                    JSONObject processedComponentData = processedTemplate.getJSONObject(componentName); 
                    while (it2.hasNext()) {
                        String propertyName = it2.next();
                        processedComponentData.put(propertyName, componentData.get(propertyName));
                    }
                    processedTemplate.put(componentName, processedComponentData);
                } else {
                    //Component is not already present. Simply copy
                    processedTemplate.put(componentName, template.get(componentName));
                }
            }
            return processedTemplate;
        } else {
            return template;
        }
    }
}

On debugging I noticed that the code executes fine until after the while loop. Soon after the while loop, it jumps across the if/else and returns "template" instead of "processedTemplate". Even the resulting object indicates that "template" is being returned. I've tried clearing the binaries, recreating the emulator, and executing it on the actual device. The weird behavior persists. Could you someone tell me why this happens?

EDIT: The correct object IS being returned. My earlier comment that "template" was being returned was because of a bug where I was not saving the returned process object back into the HashMap.
I was simply doing

if (template.has("extends"))
    processInheritance(template));

However the control still seems to jump across. An problem with Eclipse, I suppose.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

柳絮泡泡 2024-10-17 10:52:23

我尝试使用 Eclipse 调试您的代码,如果我正确理解它的目标,它似乎可以工作。调试器的行为似乎如您所描述的那样:当它应该返回processedTemplate时,它会跳到带有template的行。然而,正如预期的那样,processedTemplate 被返回。调试器似乎总是从最后一个 return 语句跳出函数。

我想说问题不在于这段代码。也许您应该发布一些出现问题的 JSON 示例文件。

I tried to debug your code using Eclipse and it seems to work if I understand it's goal correctly. The debugger seems to behave as you described: when it should return processedTemplate, it skips to the line with template. However, processedTemplate is returned, as expected. The debugger seems to jump out of a function always from the last return statement.

I would say that the problem is not in this code. Maybe you should post some JSON example files with which the problem occurs.

小糖芽 2024-10-17 10:52:23

我的猜测是因为它是一种递归方法,并且您有效地删除了一个键,然后迭代了剩余键的列表,因此在递归过程中这会以某种方式搞砸。尝试不要删除“extends”键,而是在迭代键集时忽略它。

My guess is because it's a recursive method and you are effectively removing a key and then iterating over the list of remaining keys, that this gets messed up somehow during recursion. Try not removing the "extends" key but rather ignore it when iterating through the key set.

情徒 2024-10-17 10:52:23

虚拟机永远不会出现这种错误,因此您的递归方法很可能是一个错误。
我无法立即确定它,但有几个 System.out.println(template);可能有帮助。

The virtual machine would never have this kind of an error, so there is a good chance your recursive approach as a bug.
I can't pinpoint it right away, but a couple System.out.println(template); might help.

未蓝澄海的烟 2024-10-17 10:52:23

更改如下代码似乎已经解决了问题,但原始代码片段的问题仍然存在。

private JSONObject processInheritance(JSONObject template) throws AssetLoadingException {
        try {
            if (!template.has("extends")) {
                return template;
            } else {
                //Everything else
            }
        } catch (JSONException ex) {
            throw new AssetLoadingException(ex);
        }
    }

Changing the code as below seems to have fixed the issue, but the problem with the original code snippet still remains.

private JSONObject processInheritance(JSONObject template) throws AssetLoadingException {
        try {
            if (!template.has("extends")) {
                return template;
            } else {
                //Everything else
            }
        } catch (JSONException ex) {
            throw new AssetLoadingException(ex);
        }
    }
二手情话 2024-10-17 10:52:23

发生这种情况是因为您将处理所有对象的继承,直到获得根对象。 (没有“extends”值的那个。)

因此,您找到的第一个返回是 else 分支中的返回。

重复我的解释:

这是你的精简代码:

private JSONObject processInheritance(JSONObject template) throws AssetLoadingException {
        try {
            if (template.has("extends")) {

                JSONObject parentTemplate = processInheritance(templates.get(parentTemplateName));

                }
                return processedTemplate;
            } else {
                return template;
            }
        } catch (JSONException ex) {
            throw new AssetLoadingException(ex);
        }
    }

如果你有序列 ROOT <- C <- B <- A (其中 B 扩展 A 等等)并且开始评估 A,将会发生以下情况:

  1. 进程 A
  2. A 正在扩展 B(有“extends”),因此进程 B
  3. B 正在扩展 C,因此进程 C
  4. C 正在扩展 ROOT,因此进程 ROOT
  5. ROOT不扩展任何内容,因此输入 else 并返回模板。

(那么处理完C、B、A后会有一个顺序返回)

This happens because you will processInheritance of all objects, until you get the root one. (The one that doesn't have an "extends" value.)

Hence, the first return that you find is the one in the else branch.

Repeating my explanation:

Here is your striped-down code:

private JSONObject processInheritance(JSONObject template) throws AssetLoadingException {
        try {
            if (template.has("extends")) {

                JSONObject parentTemplate = processInheritance(templates.get(parentTemplateName));

                }
                return processedTemplate;
            } else {
                return template;
            }
        } catch (JSONException ex) {
            throw new AssetLoadingException(ex);
        }
    }

If you've got the sequence ROOT <- C <- B <- A (where B extends A and so-on) and start evaluating A, this is what will happen:

  1. process A
  2. A is extending B (has "extends"), so process B
  3. B is extending C, so process C
  4. C is extending ROOT, so process ROOT
  5. ROOT extends nothing so enter the else and return template.

(then there will be a sequence of returns after finishing processing C, B and A)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文