【问题标题】:Another java.lang.IndexOutOfBoundsException, but index < size另一个 java.lang.IndexOutOfBoundsException,但 index < size
【发布时间】:2012-05-15 12:28:49
【问题描述】:

我刚刚在我的小程序中将所有数组移植到 ArrayList(由于我非常缺乏 Java 知识,我不知道基本数组类型没有任何“.add”选项),一切看起来都很好。 ..除了不时抛出异常,但它自相矛盾:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 17, Size: 21
    at java.util.ArrayList.rangeCheck(ArrayList.java:604)
    at java.util.ArrayList.get(ArrayList.java:382)
    at guay.Puntitos.AumentarTamano(Puntitos.java:346)
    at guay.Guay$MiMouse.mouseMoved(Guay.java:226)
    at java.awt.Component.processMouseMotionEvent(Component.java:6550)
    at java.awt.Component.processEvent(Component.java:6274)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Window.processEvent(Window.java:2016)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Window.dispatchEventImpl(Window.java:2713)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:680)
    at java.awt.EventQueue$4.run(EventQueue.java:678)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Java 指向我的代码块是这样的:

for (int i = 1; i < elipsasCol.size(); i++) {
  if (elipsasCol.get(i) != null && elipsasCol.get(i).contains(mouse)) {
     // This line                    
     double modulo = Math.sqrt(Math.pow(mouse.x - elipsasCol.get(i).getCenterX(), 2) 
                             + Math.pow(mouse.y - elipsasCol.get(i).getCenterY(), 2));
  }
}

该错误不会对程序的性能造成任何问题。但是,我希望有人能向我解释这个异常的原因。

谢谢!

【问题讨论】:

  • 你可能想从 0 开始循环,除非它是一个特殊的值......
  • 你的循环为什么从@1开始而不是从0开始?
  • 不使用for-each loop有什么原因吗?
  • 那个 Index:17, Size:21 非常可疑。 ArrayList 的源代码位于docjar.com/html/api/java/util/ArrayList.java.html。行号与您在堆栈跟踪中显示的内容完全一致,但从该代码看来,该消息可能 不会出现。我很想在这里看到最终的答案。您是否有其他线程添加到此处的列表中?
  • 我感觉这是一个线程问题。正如@RayToal 指出的那样,该消息应该是不可能的;除非,您在抛出异常和创建消息之间添加到列表中。

标签: java indexoutofboundsexception


【解决方案1】:

这将是一个并发修改问题。这是您得到该错误的唯一方法。

您没有收到并发修改错误的原因是因为您进行循环的方式不会创建迭代器,因此没有机会引发并发修改错误。

我建议在您的数组列表上同步或使用诸如CopyOnWriteArrayList之类的东西。

编辑:抱歉,CopyOnWrite 不适用于此特定问题。您需要切换到一个 foreach 循环才能使其成为一个选项。

回应您的以下评论:

同步:

synchronized(elipsasCol){
for (int i = 1; i < elipsasCol.size(); i++) {
  if (elipsasCol.get(i) != null && elipsasCol.get(i).contains(mouse)) {
    // This line                    
    double modulo = Math.sqrt(Math.pow(mouse.x - elipsasCol.get(i).getCenterX(), 2)
                            + Math.pow(mouse.y - elipsasCol.get(i).getCenterY(), 2));
  }
}

然后在您触摸的其他任何地方添加类似的synchronized(elipsasCol){} elipsasCol

for (T obj : elipsasCol) {
  if (obj != null && obj.contains(mouse)) {
    // This line                    
    double modulo = Math.sqrt(Math.pow(mouse.x - obj.getCenterX(), 2)
                            + Math.pow(mouse.y - obj.getCenterY(), 2));
  }
}

这很可能会引发并发修改错误。此时您可以将 ArrayList 切换为 CopyOnWriteArrayList 或围绕它进行同步。

【讨论】:

  • 没有for每个循环它会工作吗?据我了解,javadoc CopyOnWriteArrayList 在创建新迭代器时会有所帮助(我们用于每个循环)。对吗?
  • @NikitaBeloglazov 你是对的。他需要切换到 for each 循环,然后他可以使用写入时的副本来避免他将遇到的并发修改问题。我已经编辑了我的答案以反映这一点。
  • 哇哇哇,这超出了我的业余java水平,是时候学习了;)
  • @user1204548 我已经为你添加了示例。
  • 太棒了!你已经解决了。我没有使用你的方法,但你指出了真正的问题。我只是误解了 ArrayList 的 .add 和 .set 的使用,我正在通过销毁和创建一个新的 elipsasCol 来更新 elipsasCol,然后使用 .add 用新数据重新填充它,而我有另一种使用 elipsasCol 的方法,太傻了......无论如何,我会更加注意同步内容...
猜你喜欢
  • 2019-12-10
  • 2020-03-16
  • 1970-01-01
  • 2018-08-01
  • 2020-02-01
  • 1970-01-01
  • 2022-06-13
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多