2014-10-01 17 views
0

我目前遇到了下列问题,使用Java 8:的ArrayList得到由调用方法操纵

我想传递一个ArrayList<String>作为参数传递给其他方法。这种方法,除其他事项外,去除它被赋予ArrayList的对象:

public static void calledMethod(String item, ArrayList<String> list) { 
    list.remove(item); 
} 

现在我打过电话,从主这种方法是这样的:

ArrayList<String> list = new ArrayList<String>(); 
list.add("abc"); 
Iterator<String> itr = list.iterator(); 
while (itr.hasNext()) { 
    String item = itr.next(); //<- 
    calledMethod(item, list); 
} 

在这种情况下,JVM返回java.util.ConcurrentModificationException位于上面代码中的标记行(//<-)。据我所知,这意味着该列表在被迭代时被修改。但是,这怎么发生?据我所知,Java通过价值而不是通过引用来传递方法参数。如果我的主要方法使用下面的代码调用calledMethod,不会发生错误:

ArrayList<String> list = new ArrayList<String>(); 
list.add("abc"); 
Iterator<String> itr = list.iterator(); 
while (itr.hasNext()) { 
    String item = itr.next(); //<- 
    calledMethod(item, (ArrayList<String>) list.clone()); 
} 

所以通过克隆对象calledMethod作品。这里有什么问题?


java -version:Java SE的运行时环境(建立1.8.0_20-B26)

我使用甲骨文的Java在Linux Mint的64位。

回答

5

是的,Java是通过价值。但list是什么?这是对实际的ArrayList对象的引用。当它传递给方法时,它被复制,但副本仍然引用同一个对象,所以方法的修改对调用方法是可见的,并且发生ConcurrentModificationException

当您克隆该对象时,只有该对象是该对象的副本,阻止ConcurrentModificationException

+0

你是什么意思的“['list'是]实际'ArrayList'对象的引用”吗?如果你刚刚写到Java是传值的,那么这是如何实现的呢? – s3lph 2014-10-01 21:04:42

+0

引用本身是按值传递的。这就是为什么不同方法中的'list's引用相同的'ArrayList'。就好像对象是通过引用传递的,但是它是通过值传递的引用。 – rgettman 2014-10-01 21:06:28

+0

@the_Seppi:“reference”意思是“指向对象的指针”。 'List','ArrayList'等是*引用类型*。 Java中的所有非基元类型都是引用类型。所以'list'是一个指针。复制一个指针会产生指向同一个对象的另一个指针。 – newacct 2014-10-02 01:16:14

0

是的,你可以通过值来传递它,但是你正在传递一个实际上在那种情况下传递对象引用的对象。因此,您仍然在修改calledMethod中的实际列表。

1

这里发生的事情是,你的迭代器由于列表中的“并发”修改而变得“丢失”(它并不是实际上是并发的,但它是在不通知迭代器的情况下对列表进行修改的,所以从Iterator的角度来看,就好像该列表同时被修改)

在遍历列表时,您绝不应该使用List.remove删除元素。使用Iterator.remove代替,这样的迭代器将不具有无效状态,由于消除:

Iterator<String> itr = list.iterator(); 
while (itr.hasNext()) { 
    String item = itr.next(); 
    itr.remove(); // will remove "item" and keep iterator in a correct state 
} 
+0

虽然这将防止出现ConcurrentModificationException,但OP会询问为什么在将列表传递给remove操作的方法时仍会发生异常;不是为什么在迭代时从列表中移除会导致异常。 – rgettman 2014-10-01 21:09:35

+0

“据我所知,这意味着该列表在被迭代时被修改,但是这怎么会发生?” =>我试图回答这个问题 – Joel 2014-10-01 21:12:44