2014-10-01 3 views
0

나는 현재 다음과 같은 문제, 자바 8 사용에 봉착 :ArrayList를 호출 방법에 의해 조작됩니다

내가 다른 방법에 인자로 ArrayList<String>를 통과하고 싶은가를.

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

지금 내가 주에서이 같은이 메서드를 호출 시도 :이 방법은, 무엇보다도, 그것은 주어진 된 ArrayList를에서 개체 제거이 경우

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 : 자바 SE 런타임 환경은 내가 리눅스 민트 64 비트에서 오라클 자바를 사용하고

(1.8.0_20-B26를 구축).

답변

5

예, Java는 값으로 전달됩니다. 그러나 list은 무엇입니까? 실제 ArrayList 개체에 대한 참조입니다. 메서드에 전달되면 복사되지만 복사본은 여전히 ​​동일한 개체를 참조하므로 메서드의 수정 내용이 호출 메서드에서 볼 수 있으며 ConcurrentModificationException이 발생합니다.

개체를 복제하면 개체의 복사본이 만들어져 ConcurrentModificationException이 표시되지 않습니다.

+0

당신은 "실제'ArrayList' 객체에 대한 참조 ['list'이다]"무엇을 의미합니까? 자바가 방금 쓴 것처럼 패스 - 바이 - 밸류 (value-by-value)인가? – s3lph

+0

참조 자체가 값으로 전달됩니다. 그래서 여러 메소드의'list'는 모두 같은'ArrayList'를 참조합니다. 객체가 참조로 전달 된 것처럼 보이지만 값으로 전달되는 참조입니다. – rgettman

+0

@the_Seppi : "참조"는 "개체에 대한 포인터"를 의미합니다. 'List','ArrayList' 등은 * 참조 형 *입니다. Java의 모든 비 기본 유형은 참조 유형입니다. 그래서'list'는 포인터입니다. 포인터를 복사하면 동일한 객체를 가리키는 다른 포인터가 생성됩니다. – newacct

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 연산을위한 메소드로 넘겨 질 때 예외가 여전히 발생하는 이유를 묻습니다; iterating하는 동안 목록에서 제거하는 이유가 예외가됩니다. – rgettman

+0

"내 지식이있는 한 목록은 반복되는 동안 수정되었다는 의미입니다.하지만 어떻게 될 수 있습니까?" 나는 그 대답에 노력하고있다. – Joel

관련 문제