【问题标题】:"Control variable "i" is modified"“控制变量“i”已修改”
【发布时间】:2020-04-12 02:46:30
【问题描述】:

这是我的代码,我的问题是 function tubes.remove(i--)。这是一个检查样式错误。

for (int i = 0; i < tubes.size(); i++) {
    Rectangle rect = tubes.get(i);
    rect.x -= spd;

    if (rect.x + 40  <= 0) {
        tubes.remove(i--);
        Hra.getHrac1().setSkore(0.5);
        continue;
    }
}

【问题讨论】:

  • 嗨,欢迎来到 stackoverflow。您能补充一下您遇到的错误吗?
  • 这是关于自动递增的控制变量i 得到手动tubes.remove(i--) 中由i-- 递减的警告,设为tubes.remove(i - 1)
  • 如果您收到任何错误日志,请包含错误日志
  • @Nicolas 不正确,因为 removesize() 减 1。你不能有一个无限循环,它在每次迭代时从列表中删除一个项目而不放入一个新项目来替换它.
  • @Nicolas 还有i-- 和表达式中的i = i - 1 不一样,因为i-- 的值是i 减量前的值,而@987654333 的值@ 是减量后的值。

标签: java checkstyle bluej


【解决方案1】:

在这种情况下,Checkstyle 会警告您这可能是一个错误。但实际上这不是您算法中的逻辑错误; i-- 确实减少了i 的值,但tubes.remove(i--) 也减少了tubes.size(),因此tubes.size() - i 的差异在此操作中保持不变。因此循环确实终止了。

@deHaar 的建议实际上不正确,原因有两个。

  • 首先,i - 1i-- 永远不会有相同的值,因为i-- 的值是i 在递减之前的原始值。如果您执行tubes.remove(i - 1),则不会删除当前列表元素;它将删除列表元素之前当前元素,这不是要删除的正确元素。
  • 其次,当您删除索引i 处的元素时,您要检查的下一个元素将从索引i + 1 移动到索引i 以“填补您删除的元素留下的空白”。如果你不递减i,那么你查看的下一个索引将是i + 1;实际上,您将跳过列表中的下一个元素,因此如果一行中有两个元素需要删除,您的循环只会删除一个元素。 i-- 是必需的,以便您在此之后再次查看索引 i,因为这是删除当前元素后下一个列表元素所在的位置。

也就是说,虽然tubes.remove(i--) 不是逻辑错误,但它肯定是样式错误。两位经验丰富的程序员查看了您的代码并认为它​​是错误的。这意味着您的代码对于有经验的程序员来说太棘手了,无法阅读它并可靠地计算出它的作用,因此应该以更清晰的方式重新编写它。

这里有两种更清晰的重写代码的方法:

1。向后迭代

如果i 从列表的末尾移动到开头,那么remove 方法只会围绕您已经查看过的元素移动。下一个要查看的索引将是 i - 1,无论您是否删除当前元素,因此在删除元素时无需更新 i

for (int i = tubes.size() - 1; i >= 0; i--) { // iterate backwards
    Rectangle rect = tubes.get(i);
    rect.x -= spd;

    if (rect.x + 40 <= 0) {
        tubes.remove(i); // no need to change i here
        Hra.getHrac1().setSkore(0.5);
    }
}

2。使用Iterator 删除

从您当前正在迭代的列表中删除元素很难正确处理,尤其是当您按索引删除它们时。另一方面,如果您使用Iterator 显式迭代列表,那么您根本不需要使用索引变量,并且迭代器有一个方便的remove 方法,它不会弄乱迭代用于列表中后面的元素。

for (Iterator<Rectangle> iter = tubes.iterator(); iter.hasNext();) {
    Rectangle rect = iter.next();
    rect.x -= spd;

    if (rect.x + 40 <= 0) {
        iter.remove();
        Hra.getHrac1().setSkore(0.5);
    }
}

请注意,我已经从两个解决方案中删除了 continue,因为这在循环体的末尾没有任何影响。

【讨论】:

    猜你喜欢
    • 2021-01-12
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多