您好,登錄后才能下訂單哦!
這篇文章主要介紹“java中ConcurrentModificationException異常警告怎么解決”,在日常操作中,相信很多人在java中ConcurrentModificationException異常警告怎么解決問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java中ConcurrentModificationException異常警告怎么解決”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
相信寫過一些Java代碼的人都遇到過這個異常,一般都是由以下代碼引起的:
import java.util.List;
import java.util.ArrayList;
public class Test{
public static void main(String[] args){
List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
for(String obj : list){
list.remove(obj);
}
}
}
上述代碼最終會引發java.util.ConcurrentModificationException,那么為什么呢?首先我們將上述代碼反編譯,得到如下結果(如果對foreach語法糖比較了解可以忽略):
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 4: 0
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4 // String 123
11: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: ldc #6 // String 456
20: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
25: pop
26: aload_1
27: ldc #7 // String 789
29: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
34: pop
35: aload_1
36: invokeinterface #8, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
41: astore_2
42: aload_2
43: invokeinterface #9, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
48: ifeq 72
51: aload_2
52: invokeinterface #10, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
57: checkcast #11 // class java/lang/String
60: astore_3
61: aload_1
62: aload_3
63: invokeinterface #12, 2 // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
68: pop
69: goto 42
72: return
LineNumberTable:
line 6: 0
line 7: 8
line 8: 17
line 9: 26
line 10: 35
line 11: 61
line 12: 69
line 13: 72
}
將上述代碼翻譯出來等價于下列代碼:
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Test{
public static void main(String[] args){
List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String obj = iterator.next();
list.remove(obj);
}
}
}
然后我們查看iterator.hasNext()
源碼,可以發現第一行調用了checkForComodification
方法,我們查看這個方法:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
在modCount != expectedModCount
這個條件成立的時候會拋出ConcurrentModificationException
異常,那么這個條件是怎么成立的呢?
1、首先我們查看modCount
的來源,可以發現modCount
的值等于當前List的size
,當調用List.remove
方法的時候modCount
也會相應的減1;
2、然后我們查看expectedModCount
的來源,可以看到是在構造Iterator
(這里使用的是ArrayList的內部實現)的時候,有一個變量賦值,將modCount
的值賦給了expectedModCount
;
3、最后當我們執行循環調用List.remove
方法的時候,modCount
改變了但是expectedModCount
并沒有改變,當第一次循環結束刪除一個數據準 備第二次循環調用iterator.hasNext()
方法的時候,checkForComodification()
方法就會拋出異常,因為此時List
的modCount
已經變為 了2,而expectedModCount
仍然是3,所以會拋出ConcurrentModificationException
異常;
那么如何解決該問題呢?我們查看java.util.ArrayList.Itr
(ArrayList中的Iterator實現)的源碼可以發現,在該迭代器中有一個remove
方法可以 刪除當前迭代元素,而且會同時修改modCount
和expectedModCount
,這樣在進行checkForComodification
檢查的時候就不會拋出異常了,該remove
方法源碼如下:
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
其中ArrayList.this.remove(lastRet);
這一行會改變modCount
的值,而后邊會同步的修改expectedModCount
的值等于modCount
的值;
現在修改我們開頭的程序如下就可以正常運行了:
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Test{
public static void main(String[] args){
List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println("移除:" + iterator.next());
iterator.remove();
}
}
}
到此,關于“java中ConcurrentModificationException異常警告怎么解決”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。