Java 小程序在从迭代器数组中删除对象时抛出错误

Posted

技术标签:

【中文标题】Java 小程序在从迭代器数组中删除对象时抛出错误【英文标题】:Java applet throws error in remove object from Iterator array 【发布时间】:2013-08-23 20:47:32 【问题描述】:

欢迎,我正在用 java 小程序编写一个简单的 RPG 游戏。它变得越来越复杂,许多错误都抛到了我的脸上。今天我遇到了.remove(); 方法的问题。

Exception in thread "AWT-EventQueue-1" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.remove(Unknown Source)
    at rpg.main.paint(main.java:365)
    at rpg.main.update(main.java:331)
    at sun.awt.RepaintArea.updateComponent(Unknown Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

这就是错误日志的样子。程序代码:

main.java

我们可以看到程序结束时paint methid出现错误,但我不知道是不是程序开始时启动错误引起的?

public void initLocatables()
public void initLocatables2()

我不得不承认它们是在 run 方法中的 main while 循环中调用的。 这些是出现错误的地方,在下面的评论中,我在remove();中包含了以前也引发错误的方法@

for (Iterator i = locatablesArray.listIterator(); i.hasNext();) 
               Locatable l = (Locatable) i.next(); 
               l.draw(g);
               i.remove();
            
/*while(itrLocatables.hasNext())

    Locatable l = itrLocatables.next();
    l.draw(g);
    l.remove();
*/

感谢您的回复。

【问题讨论】:

【参考方案1】:

也许当您在run() 中调用repaint() 时,paint() 会排队到 EDT 并尽快调用;在迭代locatablesArray 时,再次调用run() 中的initLocatables2(),同时重新初始化locatablesArraypaint() 的代码将产生错误。 我的建议是在特定的 init 部分中分离 init 操作并调用它一次,运行你的主循环。

还有一件事:你为什么要在initLocatables2() 中初始化Iterator(类字段itrLocatables)?如果可能,在需要时使用迭代器。

希望清楚,英语不是我的母语。

【讨论】:

【参考方案2】:

在迭代对象时,您无法从列表/地图中移除对象。这就是ConcurrentModificationException的原因

       i.remove();

如果您将绘制所有可定位元素,然后清除集合,也许您应该先将它们全部绘制,然后清除集合,而不是即时删除它们。

for (Iterator i = locatablesArray.listIterator(); i.hasNext();) 
               Locatable l = (Locatable) i.next(); 
               l.draw(g);


// Clear everything from the list
locatablesArray.clear();

【讨论】:

Iterator.remove() 用于从您正在使用Iterator 迭代的集合中删除项目。对于您的评论,正确的例外是UnsupportedOperationException 你说的都是对的,但是一定要记住ConcurrentModificationException是未选中的,如果你查看LinkedList源代码,你会发现remove()方法上的throw 来自 LinkedList javadoc:此类的迭代器和 listIterator 方法返回的迭代器是快速失败的:如果列表在创建迭代器后的任何时间以任何方式进行结构修改,除了通过迭代器自己的方式删除或添加方法,迭代器将抛出 ConcurrentModificationException。您可以从 backed-to-LinkedList 迭代器执行 Iterator.remove(),但如果有人从 extern 修改 LinkedList,您将拥有 ConcurrentModificationException 好吧,如果你想知道我发现了我的错误。它在 wile 循环中,我在其中调用 locatables 的启动,这就是数组修改太快的原因,现在我将方法调用放在 for 循环之前与 interactios。 :) 谢谢。【参考方案3】:

java.util.ConcurrentModificationException 另一种方法是使用 for 循环遍历 locatablesArray 从末尾开始与开头。这样,任何被移除的元素都不会改变数组中尚未被扫描的元素的位置。

【讨论】:

以上是关于Java 小程序在从迭代器数组中删除对象时抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

从 kivy 1.11.1 升级到 kivy 2.0.0 后,应用程序在启动时抛出错误。任何想法?

为啥迭代器指向的数据在从列表中删除后保留

Flutter导航到新页面时抛出错误

迭代器生成器装饰器

httpClient 在从 azure 反向代理调用 https 连接时抛出连接重置

使用 POST 方法上传 JSON 对象时抛出错误请求异常