깊은복사, 얕은 복사
얕은 복사
얕은 복사란?
얕은 복사(Shallow Copy)는 주소값을 복사 한다는 의미이다.
예제로 살펴보기
public class ShallowCopy {
public static void main(String[] args) {
User user1 = new User("gilbert");
User user2 = user1;
System.out.println(user1.getName() + "[" + user1 + "]");
System.out.println(user2.getName() + "[" + user2 + "]");
user2.setName("kevin");
System.out.println(user1.getName() + "[" + user1 + "]");
System.out.println(user2.getName() + "[" + user2 + "]");
}
}
class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
출력결과
출력결과를 보면 참조 변수가 가리키는 메모리 번지
는 동일하다.
여기서 주의할 점은 위의 예시에서도 알 수 있듯이, 얕은 복사의 경우 참조변수를 복사하는 것이기
때문에 결과적으로 힙영역에 있는 같은 인스턴스를 가리킨다. (동일한 주소를 참조)
따라서 둘(user1, user2) 중 하나에서 값을 변경하면 모두 값이 변하게 된다.
깊은 복사
깊은 복사란?
깊은 복사(Deep Copy)는 실제 값 을 새로운 메모리 공간에 복사하는 것을 의미한다.
깊은 복사 구현하기
[ Cloneable 인터페이스 구현 ]
public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException {
Player p1 = new Player("gilbert", 28);
Player p2 = (Player) p1.clone();
// isSameAs : 메모리 주소 비교
assertThat(p1).isSameAs(p2);
// isEqualTo : 객체의 데이터 비교
assertThat(p1.getName()).isEqualTo(p2.getName());
assertThat(p1.getAge()).isEqualTo(p2.getAge());
}
}
@Getter @Setter
@AllArgsConstructor
class Player implements Cloneable{
private String name;
private int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
출력결과
출력결과에서 볼 수 있듯 서로 다른 주소를 참조한다.
따라서 값을 변경해도 해당 참조변수가 가리키는 메모리의 데이터만 바뀌게 된다.
[ 복사 팩토리 방식 ]
public class DeepCopy {
public static void main(String[] args) {
Player p1 = new Player("gilbert", 28);
Player p2 = Player.deepCopyPlayer(p1);
assertThat(p1).isNotSameAs(p2);
assertThat(p1.getName()).isNotEqualTo(p2.getName());
assertThat(p1.getAge()).isNotEqualTo(p2.getAge());
}
}
@Getter @Setter
@AllArgsConstructor
class Player {
private String name;
private int age;
public Player(Player original) {
name = original.getName();
age = original.getAge();
}
public static Player deepCopyPlayer(Player original) {
return new Player(original);
}
}
Cloneable 인터페이스를 구현했을 때와 같은 결과를 보여준다.