왠만하면 프로젝트가 어느 정도 마무리되고 난 후 배운 것들을 블로그에 정리하는데, 이건 정말 모르고 사용하면 꽤나 고생할 것 같아서(이미 고생하긴 했다....;;) 까먹기 전에 정리해두려고 한다.
객체를 복사할 때 어떤 방식을 사용하는가?
보통 자바에서 객체를 복사/복제(clone)을 한다고 하면, 다음과 같이 쓰곤 한다.
CustomClass object = new CustomClass();
CustomClass copied = object;
위의 예시는 안전한 복사가 아니다 (경우에 따라).
ArrayList를 예시로 들어보겠다.
리스트 복사! 하면 가장 먼저 떠오르는 방식이 일반적으로 아래와 같은 방식일 것이다.
ArrayList<String> classList = new ArrayList<>();
classList.add("a");
classList.add("b");
classList.add("c");
classList.add("d");
ArrayList<CustomClass> copiedList = new ArrayList<>();
copiedList = classList; //복사?
이렇게 a = b 꼴 형식으로 대입해버리면 어떤 문제가 발생한다.
결론부터 말하자면 이 복사 방식은 얕은 복사라고 불리며, 한 쪽 리스트에 대한 접근이 다른 한 쪽에도 영향을 미친다.
...
copiedList = classList; //얕은 복사
classList.add("e"); //오리지널 리스트에 아이템 추가
위와 같은 예시에서 copiedList와 classList에는 둘 다 a, b, c, d 라는 원소를 가지고 있다.
다만 classList에서 "e"라는 원소를 추가하면, copiedList에도 "e"가 똑같이 추가된다.
...
copiedList.clear(); //초기화
마찬가지로 복사본을 초기화하면 원본 리스트도 초기화된다.
한마디로 정리하면, 이 방식은 주소값을 복사하는 것이기 때문에 얕은 복사에서는 원본과 사본 ArrayList가 완벽하게 동기화된다.
참고로 맨 위의 객체 복사도 얕은 복사에 해당한다.
반대로 깊은 복사(deep copy)라는 것이 있다.
이 복사 방식은 원본으로부터 item 자체만 복사해온다.
즉, 복사 이후에 서로에게 주는 영향은 일체 없다. (단, Class가 또 다른 Class를 포함한다면 말이 달라진다.)
깊은 복사를 사용하는 방식은 다음과 같다.
public class CustomClass implements Cloneable{
...
@Override
public Object clone(){
//CloneNotSupportedException 처리
return super.clone();
}
}
CustomClass object = new CustomClass();
CustomClass copied = (CustomClass) object.clone();
우선 해당 객체의 클래스에 Cloneable 인터페이스를 implement해주고 unimplemented function인 clone()를 선언해주면 위와 같이 사용할 수 있다.
ArrayList의 경우 깊은 복사는 다음과 같이 적용 가능하다.
copiedList.addAll(classList);
뭔가 깊은 복사도 조건에 따라서 완전한 깊은 복사가 아닌 것 같은데 좀 더 공부해보고 내용을 추가하겠음.
'JAVA' 카테고리의 다른 글
JAVA String, StringBuilder, StringBuffer 의 차이점 (0) | 2019.11.09 |
---|---|
JAVA에서 특정 폴더의 파일/디렉터리 모두 가져오기 (0) | 2019.10.09 |
JAVA 프로젝트 폴더에서 이미지 BufferedImage로 불러오기 (0) | 2019.10.09 |
SimpleDateFormat 사용법 (0) | 2019.09.20 |