자바

[Java] 배열의 깊은 복사와 얕은 복사

newwisdom 2021. 8. 1. 02:23
반응형

2021-02-10 글 

 

자바에서의 객체 복사

자바에서 객체를 복사하는 유형에는 얕은 복사와 깊은 복사가 있다.

얕은 복사

단순히 객체의 주소 값만을 복사하는 것이다.
때문에 실제로는 하나의 주소 값만을 가지고 서로 간의 값은 바뀌지 않는다.
대부분 객체를 복사한다는 말은 얕은 복사가 아닌 깊은 복사를 의미한다.
Example

public class Array_Shallow_Copy{
    public static void main(String[] args)  {
        int[] arr1 = { 1, 2, 3};
        int[] arr2 = arr2;
    }
}

= 연산자는 주소를 이어줌을 의미하는데,
위 예제는 a의 배열을 b배열로 = 연산자를 활용하여 대입했기 때문에 얕은 복사가 된다.
즉 같은 주소값을 가진다. (참조에 의한 복사)
때문에 arr2의 값을 수정하면 arr1의 값도 같이 수정된다.

깊은 복사

객체의 실제 값을 새로운 객체로 복사한다.
복사된 배열이나 원본 배열이 변경될 때 서로 간의 값은 바뀌지 않는다.

자바에서는 배열을 깊은 복사할 수 있는 여러가지 메서드를 제공하고 있다.

Obejct.clone()

public class Array_Copy_Clone{
    public static void main(String[] args)  {
        int[] a = { 1, 2, 3, 4 };
        int[] b = a.clone();
    }
}

가장 보편적인 방법으로 깊은 복사를 할 때 사용된다.

But. 객체 배열의 경우 clone()을 사용하면 깊은 복사가 되지 않는다!
그 이유는 객체는 주소값을 가지고 있기 때문이다. (일반 자료형의 배열만 깊은 복사가 가능하다)
마찬가지로 2차원 배열의 경우도 각각의 row에 대한 주소값이 존재하기 때문에 깊은 복사가 되지 않는다.

또 해당 메소드는 객체의 클로닝을 위한 메소드인데
추가로 객체 클로닝에 관하여 글을 읽어보면 좋다.

System.arraycopy()

public class Array_Copy_ArrayCopy{
    public static void main(String[] args)  {
        int[] a = { 1, 2, 3, 4 };
        int[] b = new int[a.length];
        System.arraycopy(a, 0, b, 0, a.length);
    }
}

System.arraycopy(src, srcPos, dest, destPos, a.length); 형식으로 사용한다.

일차원 객체 배열 복사하기

public static Pos[] deepCopy(Pos[] src){
    if(src == null) return null;
    Pos[] dest = new Pos[src.length];
    for(int i=0; i<src.length; i++){
        src[i] = new Pos(src[i].a, src[i].b);
    }
    return dest;
  }

for 문을 돌 때마다 새로운 객체를 생성하여 직접 값을 넣어준다.
그래야 새로운 객체를 담은 다른 배열로 깊은 복사된 배열을 가질 수 있다.

참고 자료

반응형