코딩못하는사람

Cloneable 인터페이스 deepcopy 본문

자바 메모장/개념 및 문법

Cloneable 인터페이스 deepcopy

공부절대안함 2021. 2. 10. 18:36

mutable한 객체들을 deepcopy하지 않고 사용하다가 코드를 짤 때 실수한 경험이 많다.

그래서 이번에 확실히 정리했다.

 

DeepCopy (깊은 복사)

일반적인 객체 deepcopy

Object클래스의 clone()메서드를 사용하면 객체를 deepcopy해줄 수 있다.

따라서 객체들이 Object 클래스의 clone()메서드를 가지고 있다면 쉽게 깊은 복사를 할 수 있다.

예를들어 Array의 API를  보자. public final class Array extends Object 라고 되어 있다.

따라서 clone을 사용하면 쉽게 deepcopy를 할 수 있다.(primitive 타입 배열일때)

 

내가 만든 클래스 인스턴스의 deepcopy

내가 만든 class의 deepcopy를 하려면 Cloneable 인터페이스를 클래스에 구현해 주어야 한다.

Cloneable 의 clone()메서드를 오버라이드 해주면 된다.

출력은 false로 다른 주소를 가지고 있음을 알 수 있다.

객체의 필드에 immutable 객체만 있다면 deepcopy는 깔끔하게 된다.

 

 

문제는 필드에 mutable한 객체가 있거나 내가 만든 class 인스턴스가 있을 때이다.

 

객체속에 객체가 있을 때

객체 필드 속에 또 다른 객체가 존재하면

필드에 있는 객체에 Cloneable을 다시 구현해서 clone메서드를 구현해주면 된다

 

위 코드는 mann 클래스에  live 클래스를 필드로 두어 구현했다.

현재의 코드에는 live 클래스가 복사 deepcopy가 되지 않아서

가장 큰 a,b객체의 주소는 달라서 false가 나오지만

두번 째 출력인 a.L과 b.L의 출력은 true 가 된다(주소가 같다)

 

하지만 주석문을 풀게되면 아래의 live클래스도 clone메서드가 구현되고

mann클래스에서 두번에 걸쳐 복사 하므로써 false와 false가 출력되게 된다.

 

이번에는 mutable 객체인 ArrayList가 필드에 L로 선언되어 있었다고 가정해보자.

API를 보면 ArrayList는 Cloneable 를 구현하고 있으므로 바로 clone()메서드 구현이 가능하다.

따라서 (ArrayList)L.clone()을 해주면 복사가 된다.

 

추가적으로 mutable 객체와 immutable 객체를 deepcopy 했을 때

mutable객체는 바로 주소가 바뀌었고 immutable객체는 값을 변경해줄 때 주소가 바뀌었다.

 

2차원 배열의 deepcopy

int [][] a=new int [][] {{1,2,3},{4,5,6}} 의배열을 선언한다고 가정해보자.

int [][] b=a.clone();을 하게되면 a와 b의 주소는 같아지지만 내부 배열의 주소는 같아서

외부 a,b는 deepcopy a[0]과 b[0] , a[1]과 b[1]의 주소는 같은 상태라서

a[0][0]=을 0으로 바꾸면 b[0][0]도 0이 된다.

따라서 2차원 배열을 deepcopy할때는 배열의 길이만큼 배열을 만들고

각 배열의 값에 내부 배열을 copy해서 놓는 방식으로 간단하게 deepcopy할 수 있다.

 

 

 

 

 

 

[4, 5, 6]이 맞게 출력되고 주소도 다르게 된다.

'자바 메모장 > 개념 및 문법' 카테고리의 다른 글

hashCode()와 equals() - Collection(2)  (0) 2021.02.12
배열과 Collections 프레임 워크(1)List  (0) 2021.02.11
Immutable,mutable 객체  (0) 2021.02.10
JVM 메모리 구조 정리  (2) 2021.02.09
배열 정렬 Array.sort()  (0) 2021.02.08
Comments