Java 깊은 복사(Deep Copy),얕은 복사(Shallow Copy) 에 대해서..

이동명·2023년 5월 23일
0
post-thumbnail

Java 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)

이번에 정리할 내용은 자바에서의 깊은 복사와 얕은 복사 입니다.

int[] arrData = {1,2,3};
int[] arrData2 = arrData;
		
arrData2[0] = 10;
System.out.println(arrData[0]); -> 10

원한 값은 1이 나오길 바랬지만 원하지 않는 값이 나온 이유를 살펴 봅시다.

깊은 복사(Deep Copy)는 '실제 값'을 새로운 메모리 공간에 복사하는 것을 의미하며,
얕은 복사(Shallow Copy)는 '주소 값'을 복사한다는 의미입니다.

얕은 복사(Shallow Copy)

복사하려는 원본 객체에 대해서 새로운 단일 객체 또는 새로운 복합 객체를 만들고 원본 객체를 참조한다. 즉, 다양한 복합 멤버 변수를 갖고 있는 객체가 인스턴스가 생성될 때 인스턴스화 되면서 메모리에 할당된 주소의 값을 참조한다. 또한 얕은 복사는 복사 객체가 원본 객체에 종속적이다.
얕은 복사는 주소에 의한 참조 즉, call-by-reference와 유사한 개념이 된다.

장점

  • 빠르고 간결하다.

단점

  • 바로 위의 다형성의 장점이 존재하지만 값을 참조하는 것이므로 원본 객체에 종속적인 단점도 존재한다.
    원본 객체가 수정되는 경우 복사 객체가 원본 객체와 동일하게 변동이 생긴다.

깊은 복사(Deep Copy)

int[] arrData = {1,2,3};
int[] arrData2 = arrData.clone();
		
arrData2[0] = 10;
System.out.println(arrData[0]); -> 1

이제서야 원하는 값이 나온다.

복사하려는 원본 객체에 대해서 새로운 단일 객체 또는 새로운 복합 객체를 만들고 원본 객체를 대상으로 인스턴스화할 수 있는 클래스 내부의 클래스 변수(static)와 메서드(static)뿐 아니라 인스턴스 값 모두를 복사하여 원본 객체로부터 독립적인 객체를 생성한다.
깊은 복사는 새로운 객체가 원본 객체 자체를 Copy 하는 것이다. 즉, call-by-values와 유사한 개념이 된다.

장점

  • 객체 자체를 복사하기 때문에 독립된 새로운 객체로 다형성을 부여하여 사용하거나 재정의할 수 있다.

단점

  • 모든 인스턴스 값을 갖고 오기 때문에 얕은 복사에 비해서 상대적으로 느리고 복잡하다.

다른 깊은 복사 방법

깊은 복사를 위해 clone() 메서드 대신 객체 직렬화를 이용하거나 복사 생성자를 이용하는 방법이 있습니다. 이 글에서는 복사 생성자를 통한 방법에 대해 알아보겠습니다.

복사 생성자

복사 생성자는 생성자의 매개변수로 자기 자신과 같은 타입의 객체를 받아서 작성합니다. 이렇게 작성된 생성자 내에서 새로운 객체의 속성에 원본 객체의 속성을 할당합니다.

이 때 중요한 점은 복사 생성자 내의 레퍼런스들도 복사 생성자의 체인을 통해서 복사해주어야한다는 점입니다.

class Apple {
	int size;
	public Apple(Apple a){
		this.size = a.size;
	}
}
class Tree {
	int height;
	Apple apple;
	public Tree(Tree t){
		this.height = t.height;
		this.apple = new Apple(t.apple);
	}
}

복사 생성자의 장점

Object.clone() 에 비해 복사 생성자는 다음과 같은 장점을 갖습니다.

  • 인터페이스 구현 및 예외 처리 불필요
    - Cloneable 및 CloneNotSupportedException

  • 타입 다운캐스팅 불필요
    - 오버라이딩 및 상위 타입의 객체의 타입캐스팅 불필요

  • 객체 생성자 제어
    - 오버라이딩 및 상위 타입의 객체의 타입캐스팅 불필요

  • 타입 다운캐스팅 불필요
    - clone() 메서드 호출 시 생성자를 동작시킬 수 없으나, 복사와 동시에 임의의 생성자를 호출가능따라서 final 멤버도 복사하거나 제어 가능

  • ex) LinkedList 의 복사 생성자

public LinkedList(Collection<? extends E> c) {
	this();
	addAll(c);
}

참고


깊은 복사(Deep Copy) vs 얕은 복사(Shallow Copy)
Object.clone(), 얕은 복사, 깊은 복사, 복사 생성자
얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)

profile
Web Developer

0개의 댓글