티끌모아 로키산맥 🏔
search
![](https://t1.daumcdn.net/tistory_admin/static/manage/images/r3/default_L.png)
로ᄏl
배움에 끝은 없다... 개발 또한 그러하다.
Today
Yesterday
자바로 개발을 하다보면 객체를 복사할 일이 있다. 이럴 때 나오는 개념이 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) 개념인데, 두 개념의 차이를 간단하게 말하면 얕은 복사는 객체의 참조값(주소값)을 복사하고, 깊은 복사는 객체의 실제 값(value)를 복사한다.
1. 얕은 복사(Shallow Copy)
2. 깊은 복사(Deep Copy)
깊은 복사를 할 때 사용하는 CloneUtils 인터페이스 사용법에 대해 정리하고자 한다.
(특히 주의해야할 점이 있기에 정확히 짚고 넘어가자)
참고한 두 포스팅 중에 '학교에서 학생 신장정보를 관리하는 예제'가 더 눈에 들어오는 것 같아서 따라서 코드를 짜봤다.
public class PhysicalInformation {
int height;
int weight;
}
public class Family {
String name;
int age;
boolean isOfficeWorkers; // 직장인 여부
}
public class Student {
String name;
int age;
Family family;
}
깊은복사를 하기 위해서 객체는 Cloneable Interface를 Implement 해야하고 clone 메서드를 오버라이드해야한다.
public class PhysicalInformation implements Cloneable{
int height;
int weight;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
이제 테스트를 해보자! 테스트는 깊은복사, 얕은복사 모두 진행한다.
//test code
PhysicalInformation physicalInformation = new PhysicalInformation();
physicalInformation.height = 180;
physicalInformation.weight = 70;
PhysicalInformation physicalInformationShalldowCopy = physicalInformation;
PhysicalInformation physicalInformationDeepCopy = null;
try {
physicalInformationDeepCopy = (PhysicalInformation) physicalInformation.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// 값 변경
physicalInformation.weight = 80;
physicalInformation.height = 170;
// 참조값, 값(height, weight) 출력
System.out.println(physicalInformation.toString()
+ " height:" + physicalInformation.height
+ ", weight:" + physicalInformation.weight);
System.out.println(physicalInformationShalldowCopy.toString()
+ " height:" + physicalInformationShalldowCopy.height
+ ", weight:" + physicalInformationShalldowCopy.weight);
System.out.println(physicalInformationDeepCopy.toString()
+ " height:" + physicalInformationDeepCopy.height
+ ", weight:" + physicalInformationDeepCopy.weight);
출력결과는 아래와 같다.
얕은복사를 한 객체의 값은 변경을 한 적이 없지만, 복사를 당한(?) 객체와 같은 참조값을 가지므로 값이 동일하게 변경되는 것을 알 수 있다.
그리고 clone()메서드로 깊은 복사를 진행한 physicalInformationDeepCopy 는 얕은 복사를 한 객체와는 달리 참조값도 다르고 그에 따라 값도 변경되지 않았음을 알 수 있다.
여기까지보면 별로 어렵지 않다는 것을 알 수 있는데, 이것은 기본 자료형, Enum, Immutable과 같이 clone을 지원하는 객체가 아닐 경우에는 별로도 clone이 되기위한 설정이 필요하다.
예로들어 Student의 필드로 Family라는 Wrapping Class가 있을 경우, 이 Wrapping Class에도 Cloneable 인터페이스를 implements하고 clone 메서드를 오버라이드 해준 다음 최상위 객체였던 Student의 clone 메서드를 아래처럼 수정해주면 깊은 복사를 할 수 있다.
public class Family implements Clonealbe {
String name;
int age;
boolean isOfficeWorkers;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 1차적으로 복사를 진행하고, 맴버 객체 자체를 복사한 다음 대입
public class Student implements Cloneable {
String name;
int age;
Family family;
@Override
public Object clone() throws CloneNotSupportedException {
Student student = (Student)super.clone();
student.family = (Family)family.clone();
return student;
}
}
아직까지 어떤 프로젝트를 진행하면서 이런 사항으로 문제점이 발생했던 적은 없다. (아직 개린이라서 그렇겠지..) 하지만 코딩테스트를 풀 때, 이런 복사가 필요한 경우가 있었고, 이 개념이 익숙하지 않아서 나름 복사랍시고 복사를 했는데 값이 같이 변해서 for문을 반복해가며 새로운 객체를 만들었던 기억이 있다. 이번 포스팅으로 '얕은 복사', '깊은 복사'의 개념을 확립할 수 있었고, 다음에는 이 개념을 꼭 써야겠다는 생각이든다.
자바(Java)로 개발을 하다보면 한번쯤 객체를 복사하는 로직을 작성할때가 있다. 그때마다 나오는 이야기인 Shalldow Copy 와 Deep Copy. 한국어로 표현하면 얕은 복사와 깊은 복사라고 이야기를 하는데 이 두 개념의 차이는 아주 간단하다. 객체의 주소값을 복사하는지, 아니면 객체의 실제 값(value)를 복사하는지.
프로그래머스 윈터코딩(2019) 문제1: 멀쩡한 사각형 (0) | 2019.11.24 |
---|