배열, 컬렉션, 객체 등 참조 타입의 값은 생성시 주소가 생기고 대입으로 복사 했을 때 주소가 저장된다.
두 변수 모두 같은 값을 가지고 있지만 같은 주소를 가지고 있기 때문에 둘 중 하나를 수정하면 다른 하나도 같이 수정된다.
ex)
// 얕은 복사
int[] a = { 1, 2, 3, 4 };
int[] b = a; // 얕은 복사
b[0] = 3; // b 배열의 0번째 순번값을 3으로 수정했습니다. (1 -> 3)
System.out.println(a[0]); // 출력 3 <- a 배열의 0번째 순번값도 3으로 조회됩니다.
얕은 복사의 경우 값을 조회하는 경우에 사용되는 것은 문제가 안되나 값의 수정이 필요한 경우 즉, 독립된 두 변수가 값은 동일한 것을 원할 경우 문제가 된다.
그래서 변수가 내포하고있는 값을 직접 복사해줘야 한다.
ex)
// 깊은 복사
int[] a = { 1, 2, 3, 4 };
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i]; // 깊은 복사
}
b[0] = 3; // b 배열의 0번째 순번값을 3으로 수정했습니다. (1 -> 3)
System.out.println(a[0]); // 출력 1 <- 깊은 복사를 했기때문에 a 배열은 그대로 입니다.
자바의 경우 .clone() 이라는 메서드로 깊은 복사를 지원한다.
// 깊은 복사 메서드
// 1. clone() 메서드
int[] a = { 1, 2, 3, 4 };
int[] b = a.clone(); // 가장 간단한 방법입니다.
// 하지만, clone() 메서드는 2차원이상 배열에서는 얕은 복사로 동작합니다!!
자바의 배열은 .copyOf()라는 깊은 복사 함수를 지원한다.
// 깊은 복사 메서드
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// 2. Arrays.copyOf() 메서드
int[] a = { 1, 2, 3, 4 };
int[] b = Arrays.copyOf(a, a.length); // 배열과 함께 length값도 같이 넣어줍니다.
}
}
위에 적힌 대로 2차원 배열 혹은 객체의 배열 같은 경우 clone으로 복사 하여도 얕은 복사로 시행된다 왜냐하면 clone의 경우 a의 내부 값만 복사하는 것이기 때문이다.
a가 주소를 값으로 가진 경우엔 clone으로 그 형태만 복사해온다.
ex) 객체 리스트
//Student라는 클래스가 있습니다.
List<Student> arr1 = new ArrayList<>();
for (int i = 0; i < 5 ; i++) {
arr1.add(new Student("jack", "1234"));
}
ArrayList<Student> arr2 = (ArrayList<Student>) arr1.clone();
System.out.println("arr1 = " + arr1);
System.out.println("arr2 = " + arr2);
arr2.get(1).setName("tom");
System.out.println("arr1 = " + arr1);
System.out.println("arr2 = " + arr2);
result)
.clone() 외에도 List.addAll() Collections.copy() 등등 다양한 복사 메서드가 있다.
다양한 복사 메서드가 있지만 2차원 배열의 깊은 복사를 하기 위해선 개발자가 직접 복사하는 수 밖에 없다.
ex) 객체 리스트
List<Student> arr1 = new ArrayList<>();
for (int i = 0; i < 5 ; i++) {
arr1.add(new Student("jack", "1234"));
}
// ArrayList<Student> arr2 = (ArrayList<Student>) arr1.clone();
List<Student> arr2 = new ArrayList<>();
for(Student s : arr1){
arr2.add(new Student(s.getName(),s.getStudentNumber()));
}
System.out.println("arr1 = " + arr1);
System.out.println("arr2 = " + arr2);
arr2.get(1).setName("tom");
System.out.println("arr1 = " + arr1);
System.out.println("arr2 = " + arr2);