Android/Java 方法的奇怪问题。控制似乎跳过 if/else 块
在下面的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我尝试使用 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 withtemplate
. However,processedTemplate
is returned, as expected. The debugger seems to jump out of a function always from the lastreturn
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.
我的猜测是因为它是一种递归方法,并且您有效地删除了一个键,然后迭代了剩余键的列表,因此在递归过程中这会以某种方式搞砸。尝试不要删除“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.
虚拟机永远不会出现这种错误,因此您的递归方法很可能是一个错误。
我无法立即确定它,但有几个 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.
更改如下代码似乎已经解决了问题,但原始代码片段的问题仍然存在。
Changing the code as below seems to have fixed the issue, but the problem with the original code snippet still remains.
发生这种情况是因为您将处理所有对象的继承,直到获得根对象。 (没有“extends”值的那个。)
因此,您找到的第一个返回是
else
分支中的返回。重复我的解释:
这是你的精简代码:
如果你有序列
ROOT <- C <- B <- A
(其中 B 扩展 A 等等)并且开始评估 A,将会发生以下情况:有“extends”)
,因此进程 Belse
并返回模板。(那么处理完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:
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:has "extends")
, so process Belse
and return template.(then there will be a sequence of returns after finishing processing C, B and A)