Gentle Breeze
[JAVA] 반복문 내에서 List 객체에 add 할 때 메모리 참조 오류 본문
사실 이 부분은 엄밀히 개발자의 무지(無知, Call by Value / Reference)에서 오는 오류로 JAVA 프로그램 내부의 문제라고 보기는 애매하다.
하지만 여러 프로젝트를 수행하며 지켜와 본 바에 따르면 생각보다 많은 개발자들이 이 현상에 대한 원인을 명확히 알지 못해 반복적으로 이 오류를 범하고 있기에 포스팅을 남겨본다.
- 잘못 된 코드 예시
import java.util.List;
public class test {
public static void main(String[] args) {
String[] strArray = {"aaa", "bbb", "ccc"};
List<VO> list = new ArrayList<VO>();
VO vo = new VO();
for (int i=0; i<3; i++){
vo.setValue(strArray[i]);
list.add(vo);
}
}
}
일반적으로 개발자들은 위와같이 코드를 짜고 위 프로그램을 돌려보면 list 객체에는 "ccc" 라는 값의 value 변수를 가진 vo 객체가 3번 add 되어 있는 결과를 얻고는 그 원인을 찾지 못해 엉뚱한 사람을 탓하거나 스스로 멘붕에 빠지는 결과를 얻는 경우를 종종 보게 된다.
이 상황을 겪어본 경험이 있는 개발자라면 경험을 통해 빠르게 코드를 수정하지만 단순히 짐작에 의한 수정일 뿐 오류의 근본적 원인은 알지 못하는 경우도 있었다.
결론적으로는 아래와 같이 수정하면 원하는 결과를 얻을 수 있다.
- 수정한 코드 예시
import java.util.List;
public class test {
public static void main(String[] args) {
String[] strArray = {"aaa", "bbb", "ccc"};
List<VO> list = new ArrayList<VO>();
for (int i=0; i<3; i++){
VO vo = new VO();
vo.setValue(strArray[i]);
list.add(vo);
}
}
}
이제 맨 처음 코드에서 문제가 발생한 원인을 알아보자.
이 경우 JAVA 소스 내에서 new VO(); 를 수행하는 순간 하나의 객체가 메모리 상에 생성된다. 이 vo 안의 value 변수(이름)에 데이터를 여러번 바꾼다 하여도 결국엔 같은 메모리 주소의 값만 변경되고 마지막에 적용된 데이터인 "ccc"가 최종 데이터 값(이름)이 된다.
좀 더 이해하기 쉽게 설명하자면 아이(vo)를 3명 낳아 각각의 아이들에게 "aaa", "bbb", "ccc" 라는 이름을 부여해야 하는데 1명의 아이(vo)만 낳아 3개의 이름을 한명의 아이에게 부여하다보니 가장 마지막에 지어준 "ccc" 라는 이름이 그 아이의 이름이 되어버린 것이다.
new 를 이용해 객체를 계속 재생성 하게 된다면 그만큼 많은 메모리 공간을 사용하게 되고 gc (garbage collection) overhead 가 증가해 성능상의 문제가 발생할 수 있으나 이 경우에는 어쩔수 없이 반복문 내에서 new 를 통해 객체를 매 번 재 생성 해 각각 다른 속성을 가진 객체로 만들어 각각 다른 메모리 주소를 참조하고 있는 이 객체들을 list 로 묶어 주어야만 한다.
상황에 따라 list 에 add 하는 부분을 void 를 반환하는 별도의 method 로 구현하여도 된다. 이 때에도 해당 method 안에 new 를 이용해 VO 객체를 재생성하는 코드가 삽입되어야 한다.
'⑨ 직무역량강화 > JAVA' 카테고리의 다른 글
[JAVA] Java Heap Space OOM (0) | 2012.07.04 |
---|---|
[JAVA] LOG4J (0) | 2012.02.29 |
[JAVA] javac options (0) | 2012.02.15 |