(JAVA) 얕은 복사, 깊은 복사

InAnarchy·2022년 10월 24일
0

JAVA

목록 보기
18/18
post-thumbnail

선요약
얕은 복사: 복사한 배열이 원래 배열의 주솟값을 가져옴
깊은 복사: 복사한 배열이 원래 배열을 그대로 가져옴

얕은 복사

  • 주소값을 복사하여 주소로 값을 참조함
  • 한 쪽이 바뀌면 다른 쪽도 바뀜
  • 객체를 ' = ' 로 복사하게 되면 얕은 복사가 일어난다.

1차원 배열

public class ArrCopy {
    public static void main(String[] args) {
        int[] a = new int[3];
        a[0] = 2;
        a[1] = 4;
        a[2] = 6;

        int[] b = a;
        for(int i = 0; i<a.length; i++) {
            System.out.printf("%d ", a[i]); //2 4 6
        }
        System.out.println();
        for(int i = 0; i<a.length; i++) {
            System.out.printf("%d ", b[i]);//2 4 6
        }
    }
}

이 코드에서 얕은 복사를 하면 어떻게 될까?

public class ArrCopy {
    public static void main(String[] args) {
        int[] a = new int[3];
        a[0] = 2;
        a[1] = 4;
        a[2] = 6;

        int[] b = a;
        b[0] = 3;
        b[1] = 6;
        for(int i = 0; i<a.length; i++) {
            System.out.printf("%d ", a[i]); //3 6 6
        }
        System.out.println();
        for(int i = 0; i<a.length; i++) {
            System.out.printf("%d ", b[i]); //3 6 6
        }
    }
}

복사한 배열을 수정하니 이전 원본 배열도 함께 수정되었다.

2차원 배열

import java.util.Arrays;

public class ArrCopy {
    public static void main(String[] args) {

        int[][] a = {{2, 4, 6},
                {3, 6, 9},
                {4, 8, 12}};
        int[][] b = a;
        
        b[2][2] = 4;

        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]) + "");
        }
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(b[i]) + "");
        }
    }
}
output
[2, 4, 6]
[3, 6, 9]
[4, 8, 4]
[2, 4, 6]
[3, 6, 9]
[4, 8, 4]
public class ArrCopy {
    public static void main(String[] args) {
        int[] math = {1, 2, 3, 4, 5};
        int[] newMath = new int[5];

        newMath = math;
        System.out.println("얕은 복사 결과");
        for (int i = 0; i < math.length; i++) {
            if (i == 0)
                System.out.printf("math데이터: ");
            System.out.printf("%d ", math[i]);
        }
        System.out.println("math의 주소: " + math);

        for(int i = 0; i<math.length; i++){
            if (i == 0)
                System.out.printf("newMath데이터: " );
            System.out.printf("%d " , newMath[i]);
        }
        System.out.println("newMath의 주소: " + newMath);
    }
}
얕은 복사 결과
math데이터: 1 2 3 4 5 math의 주소: [I@6d8a00e3
newMath데이터: 1 2 3 4 5 newMath의 주소: [I@6d8a00e3

깊은 복사

  • 새로운 메모리 공간에 원래 배열의 실제 값을 복사
  • 한 쪽의 변경이 다른 쪽에 영향을 주지 않음
  • clone() 메서드를 통해 깊은 복사를 할 수 있음(단 2차원 배열에서는 얕은 복사)

1차원 배열

import java.util.Arrays;

public class ArrCopy {
    public static void main(String[] args) {
        int[] a = {2, 4, 6};
        int[] b = a.clone();
        a[2] = 5;
        System.out.println("a 주소: " + a + " " + Arrays.toString(a));
        System.out.println("b 주소: " + b + " " + Arrays.toString(b));

    }
}
output
a 주소: [I@22f71333 [2, 4, 5]
b 주소: [I@13969fbe [2, 4, 6]
import java.util.Arrays;

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

        b[0] = 100;
        System.out.println("a: " + Arrays.toString(a)); //a: [2, 4, 6]
        System.out.println("b: " + Arrays.toString(b)); //b: [100, 4, 6]
    }
}

그런데..

2차원 배열

public class ArrCopy {
    public static void main(String[] args) {
        int[][] a = {{2, 4, 6},
                {3, 6, 9},
                {4, 8, 12}};

        int[][] b = a.clone(); //깊은 복사
        b[1][2] = 11;

        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]) + "");
        }
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(b[i]) + "");
        }
    }
}

이와 같은 2차원 배열은 깊은 복사를 했는데 얕은 복사가 되어버렸다.

[2, 4, 6]
[3, 6, 11]
[4, 8, 12]
[2, 4, 6]
[3, 6, 11]
[4, 8, 12]

해결방법 1: for문 + clone

import java.util.Arrays;

public class ArrCopy {
    public static void main(String[] args) {
        int[][] a = {{2, 4, 6},
                {3, 6, 9},
                {4, 8, 12}};
        int[][] b = new int[3][3];

        for(int i = 0; i<a.length; i++) {
            b[i] = a[i].clone();
        }

        b[2][2] = 4;
        
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]) + "");
        }
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(b[i]) + "");
        }
    }
}

해결방법 2: 2중 for문

import java.util.Arrays;

public class ArrCopy {
    public static void main(String[] args) {
        int[][] a = {{2, 4, 6},
                {3, 6, 9},
                {4, 8, 12}};
        int[][] b = new int[3][3];

        for(int i = 0; i<a.length; i++) {
            for(int j = 0; j<a[i].length; j++){
                b[i][j] = a[i][j];
            }

        }

        b[2][2] = 4;

        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]) + "");
        }
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(b[i]) + "");
        }
    }
}

해결방법 3. System.arraycopy()

import java.util.Arrays;

public class ArrCopy {
    public static void main(String[] args) {

        int[][] a = {{2, 4, 6},
                {3, 6, 9},
                {4, 8, 12}};
        int[][] b = new int[a.length][a[0].length]; //a와 같은 사이즈로 선언 후 

        for(int i = 0; i<a.length; i++){
            System.arraycopy(a[i],0,b[i],0,b[i].length); //복사
        }
        
        b[2][2] = 4;

        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(a[i]) + "");
        }
        for (int i = 0; i < a.length; i++) {
            System.out.println(Arrays.toString(b[i]) + "");
        }
    }
}

이 3가지 경우 모두

output
[2, 4, 6]
[3, 6, 9]
[4, 8, 12]
[2, 4, 6]
[3, 6, 9]
[4, 8, 4]
public class ArrCopy {
    public static void main(String[] args) {
        int[] math = {1, 2, 3, 4, 5};
        int[] newMath = new int[5];

        System.out.println("math의 주소: " + math);
        System.out.println("newMath의 주소: " + newMath);

        for(int i = 0; i<math.length; i++)
            newMath[i] = math[i];
        for(int i = 0; i<newMath.length; i++){
            if(i == 0)
                System.out.printf("newMath 데이터: " );
            System.out.printf("%d ", newMath[i]);
        }
        System.out.println();

        int[] mathClone = math.clone();
        System.out.println("mathClone의 주소: " + mathClone);

        for(int i = 0; i<mathClone.length; i++){
            if(i ==0)
                System.out.printf("mathClone 데이터: ");
            System.out.printf("%d ", mathClone[i]);
        }
        System.out.println();

        for(int i = 0; i<newMath.length; i++)
            newMath[i] = 0;
        System.arraycopy(math,2,newMath,0,2);
        for(int i = 0; i<newMath.length; i++){
            if(i == 0)
                System.out.printf("newMath 데이터: " );
            System.out.printf("%d ", newMath[i]);
        }
        System.out.println();
    }
}
math의 주소: [I@b684286
newMath의 주소: [I@880ec60
newMath 데이터: 1 2 3 4 5 
mathClone의 주소: [I@7ac7a4e4
mathClone 데이터: 1 2 3 4 5 
newMath 데이터: 3 4 0 0 0 
profile
github blog 쓰다가 관리하기 귀찮아서 돌아왔다

0개의 댓글