엔지니어로 가는 길

Java 배열의 얕은 복사(shallow copy)와 깊은 복사(deep copy) 본문

프로그래밍/Java

Java 배열의 얕은 복사(shallow copy)와 깊은 복사(deep copy)

탐p슨 2020. 12. 27. 14:27
728x90

fig1. 예시를 위한 Person 클래스

 

fig2. Person 클래스의 배열

 

Shallow copy

얕은 복사(shallow copy)는 객체가 아닌 객체를 참조하는 참조변수(객체의 주소)만 복사한다.

 

fig3. 얕은 복사 방법

 

fig3에서는 얕은 복사 방법 세 가지가 보인다.

 

1. 하나는 Object의 clone() 메소드

(Object의 clone() 메소드를 사용하기 위해서는 대상 클래스에서 clone() 메소드를 오버라이드 해야 하지만 얕은 복사는 객체가 복사되는 것이 아니므로 대상 클래스가 clone() 메소드를 오버라이드 하지 않아도 된다.)

2. 대입연산자 =

3. System의 arraycopy() 메소드(보다 효율적으로 얕은 복사 수행)

 

fig4. 얕은 복사 도식화

 

얕은 복사를 통해 복사되는 것은 참조변수(객체의 주소)뿐이므로 얕은 복사를 통해 만들어진 copy와 persons는 같은 Person 객체를 가리키고 있다. 따라서 copy에서 Person 객체의 값을 조작한다면 이는 persons의 Person 객체에도 영향을 미친다. 둘은 같은 객체이기 때문이다.

 

fig5. 얕은 복사된 배열에서 객체의 필드 수정
fig6. 출력 결과

 

fig6에서 볼 수 있듯, 얕은 복사된 배열에서 두번 째 원소의 name과 age를 변경하였는데 원본 배열의 두번 째 원소에도 변화가 적용되었다.

Deep copy

깊은 복사(deep copy)는 객체를 복사한다. 따라서 참조변수도 다르고 참조변수가 가리키는 객체 또한 (동등할 수는 있어도) 동일하지 않다. (동일성과 동등성의 차이)

 

fig7. 깊은 복사 방법

 

SerializationUtils의 clone 메소드를 통해 깊은 복사를 수행할 수 있다. 단, 이때 복사의 대상인 Person 클래스는 Serializable 인터페이스를 구현해야 한다. (그렇다고 따로 구현해야 할 것은 없다.)

 

 fig8. Serializable을 구현한 Person

 

만약 Serializable을 구현하지 않은 채로 SerializationUtils의 clone 메소드를 사용하면 NotSerializableException을 만나게 된다.

 

fig9. NotSerializableException

 

fig10. 깊은 복사 도식화

 

깊은 복사를 통하면 객체가 복사되므로 깊은 복사를 통해 만들어진 copy와 persons는 같은 다른(동일하지 않은) 객체를 가리키고 있다. 따라서 copy에서 Person 객체의 값을 조작한다고 한들 이는 persons의 Person 객체에 영향을 미치지 않는다. 얕은 복사 뒤에 두 배열은 객체를 통해 연결되어 있는 반면, 깊은 복사 뒤에 두 배열은 아무 연결성이 없다고 생각할 수 있다.

 

fig11. 깊게 복사된 배열에서 객체의 필드 수정
 fig12. 출력 결과

 

fig12에서 볼 수 있듯, 깊게 복사된 배열에서 두번 째 원소의 name과 age를 변경하였는데도 원본 배열의 두번 째 원소는 그대로이다.

728x90
Comments