2012-05-06 36 views
6

Tôi vừa chuyển tất cả các mảng của mình sang ArrayList (do thiếu kiến ​​thức lớn của tôi trong Java, tôi không biết kiểu mảng cơ bản không có bất kỳ ".add" nào tùy chọn) trong chương trình nhỏ của tôi và tất cả mọi thứ có vẻ tốt đẹp ... ngoại trừ việc bất cứ lúc nào một ngoại lệ được ném ra, nhưng nó mâu thuẫn với bản thân:Một java.lang.IndexOutOfBoundsException khác, nhưng chỉ mục <size

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) 

các khối mã Java chỉ cho tôi là thế này:

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)); 
    } 
} 

Lỗi không gây ra bất kỳ sự cố nào đối với hiệu suất của chương trình. Tuy nhiên, tôi sẽ đánh giá cao rằng ai đó có thể giải thích cho tôi nguyên nhân của ngoại lệ này là gì.

Cảm ơn bạn!

+1

bạn có thể muốn bắt đầu vòng lặp tại 0 trừ khi đó là giá trị đặc biệt ... –

+0

có lý do cụ thể nào để lý do vòng lặp của bạn bắt đầu @ 1 thay vì 0 không? –

+2

Có lý do nào khiến bạn không sử dụng [vòng lặp for-each] (http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html) không? – amit

Trả lời

11

Đây sẽ là vấn đề sửa đổi đồng thời. Đó là cách duy nhất bạn có thể nhận được lỗi đó.

Lý do bạn không nhận được lỗi sửa đổi đồng thời là do cách bạn đang thực hiện lặp qua không tạo ra trình lặp và do đó không có cơ hội nào được cung cấp cho lỗi sửa đổi đồng thời được ném.

Tôi sẽ đề xuất đồng bộ hóa trên danh sách theo dõi của bạn hoặc sử dụng một cái gì đó chẳng hạn như CopyOnWriteArrayList .

Chỉnh sửa: Xin lỗi CopyOnWrite sẽ không hoạt động cho vấn đề cụ thể này. Bạn cần phải chuyển sang vòng lặp foreach để nó trở thành một tùy chọn.

Đáp lại bình luận của bạn dưới đây:

Đồng bộ hóa:

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)); 
    } 
} 

và sau đó thêm một giống synchronized(elipsasCol){} xung quanh bất cứ nơi nào khác mà bạn chạm elipsasCol.

hoặc

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)); 
    } 
} 

mà rất có thể sẽ gây ra một lỗi concurrentmodification được ném. Tại thời điểm đó bạn có thể chuyển ArrayList của bạn thành một CopyOnWriteArrayList hoặc đồng bộ hóa xung quanh nó.

+2

Nó có hoạt động không cho mỗi vòng lặp không? Như tôi đã hiểu từ javadoc 'CopyOnWriteArrayList' giúp khi trình vòng lặp mới được tạo ra (chúng ta sử dụng cho mỗi vòng lặp). Nó có đúng không? –

+1

@NikitaBeloglazov bạn là chính xác. Anh ta cần chuyển sang một vòng lặp và sau đó anh ta có thể sử dụng một bản sao trên ghi để tránh vấn đề sửa đổi đồng thời mà anh ta sẽ nhận được. Tôi đã chỉnh sửa câu trả lời của mình để phản ánh điều này. – Krrose27

+0

Wowowow, điều này vượt qua mức java nghiệp dư của tôi, thời gian để nghiên cứu;) – LosTChG