https://mundol-colynn.tistory.com/127
지난 포스팅에 이어서, 자바 배열의 복사에 대해서 알아보겠습니다.
Java에서 배열의 복사는 크게 얕은 복사(shallow copy)와 깊은 복사(deep copy) 두 가지 방법이 있습니다.
얕은 복사(shallow copy)
배열의 주소 값을 복사하여 새로운 배열을 생성하는 방식입니다.
주소값을 새로 생성한 것이 아니라 "복사하여" 가져온 것이므로, 새로운 배열과 원본 배열은 같은 객체를 참조하며, 한 쪽에서 값을 변경하면 다른 쪽에서도 변경이 반영됩니다.
// int형 배열 originArray선언
int[] originalArray = {1, 2, 3, 4, 5};
// 또 다른 int형 배열 copiedArray에 originArray의 주소값을 대입
int[] copiedArray = originalArray; // 얕은 복사
System.out.println("originalArray[2]: " + originalArray[2]); // 출력: 3
System.out.println("copiedArray[2]: " + copiedArray[2]); // 출력: 3
copiedArray[2] = 10;
System.out.println("originalArray[2]: " + originalArray[2]); // 출력: 10
System.out.println("copiedArray[2]: " + copiedArray[2]); // 출력: 10
위의 코드에서 arr1 배열 변수의 주소 값을 arr2에 복사하여 같은 배열 객체를 참조하도록 하였습니다.
그리고 arr2 배열의 0번 인덱스 값을 변경하였고, 이후에 arr1 배열의 0번 인덱스 값을 출력해보았습니다. 결과적으로 출력 결과는 4가 됩니다.
깊은 복사(deep copy)
배열의 각 요소의 값을 복사하여 새로운 배열을 "생성"하는 방식입니다. 따라서 새로운 배열과 원본 배열은 서로 다른 객체를 참조하며, 한 쪽에서 값을 변경하더라도 다른 쪽에서는 변경이 반영되지 않습니다
자바 1차원 배열의 깊은 복사는 배열의 각 요소들을 새로운 배열에 복사하는 것을 의미합니다. 이때, 각 요소를 복사할 때 원본 배열의 값을 그대로 복사하는 것이 아니라, 새로운 메모리 공간을 할당하여 값을 복사합니다. 따라서 깊은 복사를 통해 새로운 배열을 생성하면, 원본 배열과 새로운 배열이 완전히 분리되어 각자의 메모리 공간을 사용하게 됩니다.
예를 들어, 다음과 같이 정수형 1차원 배열을 생성하고, 이 배열을 깊은 복사하여 새로운 배열을 생성하는 코드를 작성해보겠습니다.
int[] originalArray = {1, 2, 3, 4, 5};
int[] copiedArray = new int[originalArray.length];
for (int i = 0; i < originalArray.length; i++) {
copiedArray[i] = originalArray[i];
}
위 코드에서, 원본 배열 originalArray의 길이만큼 새로운 배열 copiedArray를 생성합니다. 그리고 for문을 이용하여 원본 배열의 각 요소를 새로운 배열에 복사합니다. 이때, originalArray[i]의 값을 그대로 대입하는 것이 아니라, copiedArray[i]에 새로운 메모리 공간을 할당하여 값을 복사합니다. 따라서 originalArray와 copiedArray는 완전히 독립적인 배열로 동작하게 됩니다.
깊은복사 방법 3가지
1. for문을 이용한 깊은 복사
가장 기본적인 방법으로, for문을 이용하여 원본 배열의 각 요소를 새로운 배열에 복사하는 방식입니다. 예를 들어, int형 배열 arr1을 깊은 복사하여 arr2에 저장하고자 할 경우 아래와 같은 코드를 작성할 수 있습니다.
int[] arr1 = {1, 2, 3};
int[] arr2 = new int[arr1.length];
for (int i = 0; i < arr1.length; i++) {
arr2[i]
}
2. Arrays 클래스의 copyOf 메소드를 이용한 깊은 복사
Java에서는 Arrays 클래스의 copyOf 메소드를 이용하여 배열의 복사를 수행할 수 있습니다.
-> java.util.Arrays 를 import하여 사용합니다.
copyOf 메소드는 원본 배열의 일부 또는 전체를 새로운 배열에 복사하는 기능을 제공합니다. 예를 들어, 위에서 사용한 int형 배열 arr1을 깊은 복사하여 arr2에 저장하고자 할 경우 아래와 같은 코드를 작성할 수 있습니다.
int[] arr1 = {1, 2, 3};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
3. System 클래스의 arraycopy 메소드를 이용한 깊은 복사
System 클래스의 arraycopy 메소드를 이용하여 배열의 복사를 수행할 수도 있습니다.
-> System클래스는 java.lang 패키지에 속해 있기 때문에, 다른 패키지에서 import 없이도 기본적으로 사용 가능합니다.
arraycopy 메소드는 원본 배열의 일부 또는 전체를 새로운 배열에 복사하는 기능을 제공합니다. 예를 들어, 위에서 사용한 int형 배열 arr1을 깊은 복사하여 arr2에 저장하고자 할 경우 아래와 같은 코드를 작성할 수 있습니다.
int[] arr1 = {1, 2, 3};
int[] arr2 = new int[arr1.length];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
위의 세 가지 방법 모두 깊은 복사를 수행할 수 있지만, 배열의 크기가 작을 경우에는 성능 차이가 크게 나타나지 않습니다. 따라서 복사할 배열의 크기와 상황에 따라 가장 적절한 방법을 선택하여 사용하는 것이 좋습니다.
Java에서 깊은 복사와 얕은 복사는 각각 다른 상황에서 사용할 수 있습니다.
얕은 복사는 복사된 배열과 원래 배열이 같은 메모리 주소를 공유하므로, 복사된 배열의 요소를 변경하면 원래 배열의 요소도 변경됩니다. 이 경우, 원래 배열을 보호하면서 복사본에서 배열 요소를 읽기만 할 필요가 있을 때 사용됩니다.
반면에 깊은 복사는 복사된 배열과 원래 배열이 서로 다른 메모리 주소를 가지므로, 복사본에서 배열 요소를 변경하더라도 원래 배열의 요소는 변경되지 않습니다. 이 경우, 원래 배열을 보호하면서 복사본에서 배열 요소를 자유롭게 변경할 필요가 있을 때 사용됩니다.
따라서, 만약 배열 요소를 변경해도 원래 배열이 변경되어도 상관없는 경우에는 얕은 복사를 사용하고, 원래 배열을 보호하면서 복사본에서 배열 요소를 자유롭게 변경해야 하는 경우에는 깊은 복사를 사용합니다.
Reference
- https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
- https://www.baeldung.com/java-deep-copy
- https://www.geeksforgeeks.org/array-copy-in-java/
- https://stackoverflow.com/questions/10805293/why-is-the-arrays-class-imported-by-default-when-a-java-file-is-compiled
'Java' 카테고리의 다른 글
[자바 / Java] 멤버변수와 클래스변수, 지역변수 (0) | 2023.03.06 |
---|---|
[자바 / Java] 자바에서 클래스란? / 클래스 vs 객체 vs 인스턴스 (0) | 2023.03.06 |
[JAVA / 자바] 배열 (part1) (1) | 2023.02.26 |
[JAVA / 자바] API vs Library: API와 Library의 차이 (1) | 2023.02.21 |
[JAVA / 자바] 컬렉션 프레임워크(Collection Framework)란 (0) | 2023.02.21 |