JAVA 깊은 복사와 얕은 복사
Java Data Type
Primitive Data Type
- 기본적(일반적)인 값을 기억하는 변수 타입
- byte, short, int, float, double, char, boolean
Reference Data Type
- 객체의 참조(Reference)값을 기억하는 변수
- class, interface, 배열 등
얕은 복사 (shallow copy)
참조에 의한 복사
원본과 사본의 참조가 같이 이루어진다
깊은 복사 (deep copy)
새로운 객체를 만들어 값은 같지만 다른 참조를 가지는 복사
배열
얕은 복사
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = a;
b[0] = 10;
System.out.println(a);
System.out.println(b);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
}
- 출력
[I@7852e922
[I@7852e922
[10, 2, 3, 4]
[10, 2, 3, 4]
- 두 배열의 주소값이 같고, 배열의 값이 함께 변경된 것을 확인할 수 있다
깊은 복사
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = a.clone();
b[0] = 10;
System.out.println(a);
System.out.println(b);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
}
}
- 출력
[I@7852e922
[I@4e25154f
[1, 2, 3, 4]
[10, 2, 3, 4]
- 두 배열의 주소값이 다르고 b 배열에서만 값의 변경이 일어났다.
- 이 외에도
Object.clone()
Arrays.copyOf()
for문
을 통해 배열 원소에 접근하여 복사
- 다차원 배열의 경우
- 다중 for문을 이용하여 1차원 배열 형태로 접근가능할 때 위의 메서드들을 사용할 수 있다
ArrayList
얕은 복사
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
ArrayList<String> list2 = list;
list2.add("d");
System.out.println(list);
System.out.println(list2);
}
}
- 출력
[a, b, c, d]
[a, b, c, d]
- list2에 d를 추가했는데 list에도 추가된 것을 확인할 수 있다
깊은 복사
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
ArrayList<String> list2 = new ArrayList<>(list);
list2.add("d");
System.out.println(list);
System.out.println(list2);
}
}
- 출력
[a, b, c]
[a, b, c, d]
class
얕은 복사
public class Main {
public static void main(String[] args) {
Student a = new Student("홍길동", 17, "010-1234-5678");
Student b = a;
b.name = "박보검";
System.out.println(a);
System.out.println(b);
}
static class Student {
String name;
int age;
String phone;
public Student(String name, int age, String phone) {
this.name = name;
this.age = age;
this.phone = phone;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", phone=" + phone + "]";
}
}
}
- 출력
// toString 생성 전
Main$Student@7852e922
Main$Student@7852e922
// toString 생성 후
Student [name=박보검, age=17, phone=010-1234-5678]
Student [name=박보검, age=17, phone=010-1234-5678]
- 두 객체가 가리키는 주소값이 같다
깊은 복사
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Student a = new Student("홍길동", 17, "010-1234-5678");
Student b = (Student) a.clone();
b.name = "박보검";
System.out.println(a);
System.out.println(b);
}
static class Student implements Cloneable{
String name;
int age;
String phone;
public Student(String name, int age, String phone) {
this.name = name;
this.age = age;
this.phone = phone;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", phone=" + phone + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.name = this.name;
student.age = this.age;
student.phone = this.phone;
return student;
}
}
}
- 출력
// toString 생성 전
Main$Student@7852e922
Main$Student@4e25154f
// toString 생성 후
Student [name=홍길동, age=17, phone=010-1234-5678]
Student [name=박보검, age=17, phone=010-1234-5678]
- 복사할 클래스에 Cloneable 인터페이스를 구현한 뒤 clone 메서드를 작성해주면 객체의 깊은 복사가 가능해진다.
- 그 후
(객체타입) 복사할객체명.clone()
을 통해 복사 가능