2022. 4. 27. 02:16ㆍJava/[도서] 자바의 정석
자바에서 객체를 복사할 때는 얕은 복사, 깊은 복사가 있습니다.
얕은 복사의 경우 객체의 주소 값을 복사하는 것이고 깊은 복사는 실제값을 복사해서 이 값을 새로운 메모리 공간에 복사하는 것입니다.
얕은 복사의 경우 여러 객체가 같은 주소를 참조하고 있기에 하나의 값이 변경되면 다른 대상의 값 또한 변경되는 문제가 발생하지만 깊은 복사는 이러한 문제가 발생하지 않습니다.
1차원 배열의 얕은 복사(Shallow Copy)
public class Copy {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
int[] b = a;
System.out.println(Arrays.toString(a)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5]
// 원본 배열 값 변경
a[1] = 22;
System.out.println(Arrays.toString(a)); // [1, 22, 3, 4, 5]
System.out.println(Arrays.toString(b)); // [1, 22, 3, 4, 5]
// 복사한 배열 값 변경
b[3] = 55;
System.out.println(Arrays.toString(a)); // [1, 22, 3, 55, 5]
System.out.println(Arrays.toString(b)); // [1, 22, 3, 55, 5]
}
}
= 연산자는 주소를 이어준다는 의미로 a의 배열을 b배열로 = 연산자를 활용하여 대입하면 얕은 복사가 됩니다.
1차원 배열의 깊은 복사(Deep copy)
public class Copy {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
System.out.println(Arrays.toString(a)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5]
// 원본 배열 값 변경
a[1] = 123;
System.out.println(Arrays.toString(a)); // [1, 123, 3, 4, 5]
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5]
// 복사한 배열 값 변경
b[3] = 789;
System.out.println(Arrays.toString(a)); // [1, 123, 3, 4, 5]
System.out.println(Arrays.toString(b)); // [1, 2, 3, 789, 5]
}
}
복사한 배열을 수정하더라도 원본 배열이 변경되지 않습니다.
위와 같이 for문을 돌려가며 일일이 값을 옮겨도 되지만 자바에서 배열을 복사할 수 있는 여러 가지 메서드를 제공하고 있습니다.
배열 복사하는 여러 가지 메서드
Object.clone()
public class Copy {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
int[] b = a.clone();
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5]
}
}
자바에서 모든 클래스의 부모 클래스는 Object 클래스이고 Object 클래스에는 clone() 메서드가 있습니다.
clone() 메소드를 이용해 새로운 배열을 생성하고 b변수에는 a변수와는 다른 참조값을 가지게 됩니다.
Arrays.copyOf() / Arrays.copyOfRange()
public class Copy {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8,9,10};
// a 배열 전체 복사
int[] b = Arrays.copyOf(a, a.length);
int[] c = Arrays.copyOfRange(a, 0, a.length);
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
System.out.println(Arrays.toString(c)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a 배열 처음부터 5개 복사
int[] b1 = Arrays.copyOf(a, 5);
System.out.println(Arrays.toString(b1)); // [1, 2, 3, 4, 5]
// a 배열 인덱스2부터 인덱스4'전'까지
int[] c1 = Arrays.copyOfRange(a, 2, 4);
System.out.println(Arrays.toString(c1)); // [3, 4]
}
}
Arrays 클래스의 copyOf(), copyOfRange() 메소드를 사용하면 배열의 전체 또는 부분을 복사할 수 있습니다.
차이점은,
Arrays.copyOf() : 시작점 ~ 원하는 length까지 복사합니다.
Arrays.copyOfRange() : 시작점의 위치 또한 지정할 수 있습니다.
System.arraycopy()
public class Copy {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8,9,10};
// a 배열 전체 복사
int[] b = new int[a.length];
System.arraycopy(a, 0, b, 0, a.length);
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a 배열 일부분 요소값 복사 (a배열 인덱스4부터 5개)
int[] c = new int[5];
System.arraycopy(a, 4, c, 0, 5);
System.out.println(Arrays.toString(c)); // [5, 6, 7, 8, 9]
// a 배열 일부분 요소값 복사 (a배열 인덱스2부터 3개)
int[] d = new int[3];
System.arraycopy(a, 2, d, 0, 3);
System.out.println(Arrays.toString(d)); // [3, 4, 5]
}
}
배열 전체 또는 일부분의 데이터를 복사할 수 있습니다.
2차원 배열의 깊은 복사
2차원 배열의 경우 앞서 살펴본 메서드로는 깊은 복사가 되지 않습니다. 이 경우 2중 for문을 돌리면서 일일이 복사해주거나 1중 for문 + 메서드들을 이용할 수 있습니다.
2중 for문
public class Copy {
public static void main(String[] args) {
int a[][] = { {1,2,3},{4,5,6},{7,8,9} };
int b[][] = new int[a.length][a[0].length];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++){
b[i][j] = a[i][j];
}
}
System.out.println(Arrays.deepToString(b)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}
}
Object.clone()
public class Copy {
public static void main(String[] args) {
int a[][] = {{1,2,3},{4,5,6},{7,8,9}};
int b[][] = new int[a.length][a[0].length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i].clone();
}
System.out.println(Arrays.deepToString(b)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}
}
System.arraycopy()
public class Copy {
public static void main(String[] args) {
int a[][] = {{1,2,3},{4,5,6},{7,8,9}};
int b[][] = new int[a.length][a[0].length];
for(int i=0; i < b.length; i++){
System.arraycopy(a[i], 0, b[i], 0, a[0].length);
}
System.out.println(Arrays.deepToString(b)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
}
}
출처 :
'Java > [도서] 자바의 정석' 카테고리의 다른 글
Scanner보다 빠른 입력 BufferedReader, StringTokenizer (0) | 2022.05.03 |
---|---|
StringBuffer클래스와 StringBuilder클래스 (0) | 2022.04.29 |
배열 오름차순, 내림차순 정렬하기 (0) | 2022.04.25 |
형변환 (문자형↔정수형↔실수형) (0) | 2022.04.23 |
String 클래스 메서드 (0) | 2022.04.21 |