본문 바로가기
Java/About Java

[Java] 얕은 복사 & 깊은 복사 & 방어적 복사

by seaweed_one 2023. 2. 13.
728x90

안녕하세요. 씨위드입니다.

오늘은 자바의 복사에 대하여 알아보겠습니다.

 

얕은 복사(Shallow Copy)란?

간단히 말하면 주소값을 복사하는 것입니다.

원본 객체를 참조하여 원본 객체에 종속적입니다.

주소값을 복사하는 방식이기 때문에 참조하고 있는 실제 데이터는 같습니다.

해서 원본 혹은 사본 변경 시 둘 다 변경되게 됩니다.

이해를 돕기 위해 간단한 코드를 작성하였습니다.

두 객체의 주소값이 같은 것을 보실 수 있습니다.

주소값을 복사하는 방식이기 때문에 빠르다는 장점을 가집니다.

이번엔 실제 데이터를 살펴볼까요?

첫 번째 프린트문에서 당연히 두 객체의 값은 같습니다.

그럼 두 개의 배열 중 하나의 값을 바꾸면 어떻게 될까요?

같은 주소값을 참조하고 있기 때문에 객체 두 개의 값 모두 변한 것을 보실 수 있습니다.

 

깊은 복사(Deep Copy)란?

객체의 실제 값을 새로운 메모리 공간에 복사합니다.

원본 객체 자체를 복사하는 방식으로 원본 객체 내부의 인스턴스 값 모두를 복사하여 독립적인 객체를 생성합니다.

예제 코드와 함께 보겠습니다.

두 객체의 메모리 값이 다른 것을 확인하실 수 있습니다.

그렇다면 얕은복사에서처럼 데이터를 한번 바꿔볼까요?

한 객체의 데이터를 변경해도 다른 객체에는 영향을 주지 않습니다.

독립된 메모리 공간에 데이터를 복사하기 때문에 얕은 복사에 비해 상대적으로 느립니다.

 

방어적 복사(defensive copy)

외부에서 객체를 변경해도 내부의 객체는 변경되지 않도록 보호하기 위해 사용합니다.

새로운 객체로 감싸서 복사하여 주소값을 공유하는 인스턴스의 관계를 끊어주는 것입니다.

 

그렇다면 깊은 복사와 무엇이 다를까요?

깊은 복사는 원본과 복사본의 모든 요소의 주소가 다르지만 방어적 복사는 내부 요소들의 주소는 원본과 공유하고 있습니다.컬랙션만 새로 생성하고 내부 요소의 주소는 그대로 옮겨 담습니다.따라서 원본 내부의 요소를 바꾼다면 복사본도 바뀌게 됩니다.

 

생성자의 인자로 받은 객체의 복사본을 만들어 내부 필드를 초기화하거나 getter 메서드에서 내부 객체 반환 시 복사본을 만들어 반환하는 방식으로 사용됩니다.

크게 두 가지 상황을 예로 들 수 있습니다.

1. 생성자의 인자로 받은 객체의 복사본을 만들어 내부 필드를 초기화

매개변수의 유효성 검사 전에 복사본을 만들어 복사본으로 유효성을 검사하게됩니다.

멀티 스레드 환경에서 원본 객체 유효성 검사 후 복사본을 만드는 찰나에 다른 스레드가 원본 객체를 수정할 위험이 있기 때문입니다.

해서 외부에서 넘겨준 객체의 값이 변경되어도 내부의 값은 변경되지 않기 위해 방어적 복사를 사용합니다.

2. getter 메서드에서 내부 객체 반환 시 복사본을 만들어 반환

 마찬가지로 getter에서도 캡슐화를 위해 방어적 복사를 사용합니다.

 

728x90

'Java > About Java' 카테고리의 다른 글

[Java] 직렬화와 역직렬화  (0) 2023.02.21
[Java] Immutable Object  (0) 2023.02.14
[Java] 객체 - 클래스  (0) 2023.02.06
[Java] 생성자  (2) 2023.01.31
[Java] Java Memory Leak  (0) 2023.01.11