1700444391
编写高质量代码:改善Java程序的151个建议 建议72:生成子列表后不要再操作原列表
1700444392
1700444393
前面说了,subList生成的子列表是原列表的一个视图,那在subList执行完后,如果修改了原列表的内容会怎样呢?视图是否会改变呢?如果是数据库视图,表数据变更了,视图当然会变了,至于subList生成的视图是否会改变,还是从源码上来看吧,代码如下:
1700444394
1700444395
public static void main(String[]args){
1700444396
1700444397
List<String>list=new ArrayList<String>();
1700444398
1700444399
list.add(“A”);
1700444400
1700444401
list.add(“B”);
1700444402
1700444403
list.add(“C”);
1700444404
1700444405
List<String>subList=list.subList(0,2);
1700444406
1700444407
//原字符串增加一个元素
1700444408
1700444409
list.add(“D”);
1700444410
1700444411
System.out.println(“原列表长度:”+list.size());
1700444412
1700444413
System.out.println(“子列表长度:”+subList.size());
1700444414
1700444415
}
1700444416
1700444417
程序中有一个原始列表,生成了一个子列表,然后在原始列表中增加一个元素,最后打印出原始列表和子列表的长度,大家想一下,这段程序什么地方会出现错误呢?
1700444418
1700444419
list. add(“D”)会报错吗?不会,subList并没有锁定原列表,原列表当然可以继续修改。
1700444420
1700444421
难道有两个size方法?正确,确实是size方法出错了,输出结果如下:
1700444422
1700444423
原列表长度:4
1700444424
1700444425
Exception in thread”main”java.util.ConcurrentModifcationException
1700444426
1700444427
at java.util.SubList.checkForComodification(AbstractList.java:752)
1700444428
1700444429
at java.util.SubList.size(AbstractList.java:625)
1700444430
1700444431
什么?居然是subList的size方法出现了异常,而且还是并发修改异常?这没道理呀,这里根本就没有多线程操作,何来并发修改呢?这个问题很容易回答,那是因为subList取出的列表是原列表的一个视图,原数据集(代码中的list变量)修改了,但是subList取出的子列表不会重新生成一个新列表(这点与数据库视图是不相同的),后面在对子列表继续操作时,就会检测到修改计数器与预期的不相同,于是就抛出了并发修改异常。
1700444432
1700444433
出现这个问题的最终原因还是在子列表提供的size方法的检查上,还记得上面几个例子中经常提到的修改计数器吗?原因就在这里,我们来看看size的源代码:
1700444434
1700444435
public int size(){
1700444436
1700444437
checkForComodifcation();
1700444438
1700444439
return size;
[
上一页 ]
[ :1.70044439e+09 ]
[
下一页 ]