【发布时间】:2014-03-10 13:45:03
【问题描述】:
我正在尝试遍历对象列表并将它们的属性打印到 xml 文件中,但是由于需要关闭标记,我需要递归遍历子对象并在返回顶部之前打印它们的属性堆栈的最高组件写出闭包标签。
然而,for 循环和递归似乎在 java 中不能很好地配合使用,因为一些奇怪的原因,当我在 for 循环内部有一个方法调用自身时,计数器“重置”(本质上,计数器变量似乎在尝试使用所有 3 个参数正常使用 for 循环时取消分配自身)在进入循环的下一次迭代时,导致无限循环。
我尝试了许多不同的方法,包括尝试在类构造函数中使计数器成为静态变量,并用 for-each 循环代替,所有这些都存在类似的问题。我最接近找到答案的是以下解决方案,将计数器传入并返回到递归方法中:
Adding counter to a loop inside a recursive method - Java
然而,虽然这适用于上面的情况,它只包含一个值,但它会导致问题,如果我不调整计数器,它现在比它需要的高一个,并导致 indexOutOfBound 异常,并且如果我在进入循环之前确实减去了计数器和/或将其分配给 0,则即使我在将计数器传回之前明确地将计数器加 1,也会返回 0。
这些都没有任何意义。这是我正在使用的代码的基本逻辑:如果有人知道这有什么问题,或者知道任何替代解决方案,请告诉我。
public int write(PrintWriter fromPortalTXTFile, String level, Integer counter){
...
if (children) {
for(;counter < childrenList.size();) {
counter++;
counter = ClassName.get(counter - 1).write(fromPortalTXTFile, level, counter);
}
}
else {
counter++;
}
return counter;
}
编辑:由于各种请求,这是整个方法代码。它包含对不同功能的引用,并且具有与我遇到的问题无关的逻辑,我无法详细说明该方法的每个部分如何工作。问题在于如果组件有子组件则输入的 for 循环,我仍然认为上面的说明更好。
// Writes the information about this BOM component out to the from_portal.txt file
public int write(PrintWriter fromPortalTXTFile, String level, Integer counter) throws Exception {
//Retrieve the item and revision of the BOM line. If
//read access is denied, skip the BOM line.
Debug.println("PERF: Inside printXMLTag: Reading BOMLine props start");
TCComponentItem item = TXDExportAction.getItem(currentComponent);
TCComponentItemRevision rev = TXDExportAction.getItemRevision(currentComponent);
//if (item == null || rev == null) {
// return null;
//}
String itemID = item.getProperty("item_id");
String revID = rev.getProperty("item_revision_id");
// Get the pdm_occ_id of the current component
String pdmOccID = TXDExportAction.getBOMLineProperty(currentComponent, "bl_occurrence_uid");
// Determine if the item is currently selected in the BOM window
Boolean isSelected = false;
//if (selectedComponents.contains(currentComponent)){
// isSelected = true;
//}
// TODO: See if it is actually needed to get the quantity of packed lines
//If the user created a single occurrence to represent
//multiple occurrences, get the quantity
int n = 1;
boolean packed = currentComponent.isPacked();
if (!packed) {
try {
//String str = icbl.getProperty("bl_quantity");
String str = TXDExportAction.getBOMLineProperty(currentComponent, "bl_quantity");
if (str != null) {
n = Integer.parseInt(str);
}
} catch (NumberFormatException e) {
//Do nothing
}
}
Debug.println("PERF: Inside printXMLTag: Reading BOMLine props complete");
//TODO: See why this is in a loop, and if it is necessary
XMLStringBuffer buf = new XMLStringBuffer();
//Loop over the BOM line n times
for (int count = 0; count < n ; count++) {
//Build the opening XML entry
//XMLStringBuffer buf = new XMLStringBuffer();
buf.startTag(TXDExportAction.BOMLINE);
buf.appendAttribute(TXDExportAction.ITEM_ID, itemID);
buf.appendAttribute(TXDExportAction.REV_ID, revID);
buf.appendAttribute(TXDExportAction.PDM_OCC_ID, pdmOccID);
buf.appendAttribute(TXDExportAction.ITEM_SELECTED, isSelected);
// If this is not the lowest level tag, don't put in the slash at the end.
// If it is, close the tag.
//TODO: Remove writing of tags, add to the BOMElement.write function.
//if (closureTags == 0){
// buf.endTagBracket();
//}
//else{
// buf.endTag();
// //Handle closure tags for parents
// for(int i = 0; i < closureTags; i++){
// buf.endTag(BOMLINE);
// }
//}
}
buf.endTagBracket();
// Step 3: write a </bomline> tag at the same level
fromPortalTXTFile.print(level);
fromPortalTXTFile.println(buf);
//buf.endTag(TXDExportAction.BOMLINE);
if (!childBOMElements.isEmpty()){
// Step 1: print tag + information
level = level + " ";
// Step 2: for each child, call child.write()
for (; counter < childBOMElements.size();){
counter ++;
//BOMElement nextElement = childBOMElements.get(index);
counter = childBOMElements.get(counter - 1).write(fromPortalTXTFile, level, counter);
}
// </Bomline> tag
//fromPortalTXTFile.println(buf.endTag(TXDExportAction.BOMLINE));
}
else
{
// If no children, close the tag with a leaflet
//fromPortalTXTFile.println(buf);
counter++;
fromPortalTXTFile.print(buf.endTag());
}
// For some reason, using a recursive function in a for loop resets the counter of the for loop.
// The only work-around is to pass the counter back as a return method.
return counter;
}
【问题讨论】:
-
你没有足够的右括号,一方面......你是否期望递归调用中的递增计数器传播给调用者?如果是这样,那就不会发生了:在 Java 中,参数是按值传递的。
-
他确实说了基本逻辑。也就是说,演示文稿中存在各种错误,将在此处要求一个实际的代码测试示例。
-
我没有复制粘贴代码,我输入了伪代码来简化阅读它的人,这样他们就不必解析数百行不相关的代码。我可以告诉你文件中的语法是正确的,并将更正示例。
-
childrenList 中有什么?您确定要传递 childrenList[counter-1] 而不仅仅是 counter-1?
-
所以,函数调用不可能是正确的,不是吗?因为
childrenList[counter-1]不是整数。逻辑似乎有问题。