01. 객체 복제란?
- 원본 객체의 필드값과 동일한 값을 가지는 새로운 객체를 생성하는 것.
- 신뢰하지 않는 영역으로 객체를 넘길 때 객체를 복제해서 넘기면 원본 객체를 안전하게 보호할 수 있다.
- 자바에서는 원본 객체가 java.lang.Cloneable 인터페이스를 구현하도록 함으로써 객체복제를 허용할 수 있다.
02. 얕은 복제 (thin clone)
- 단순히 필드값을 복사해서 객체를 복제하는 것
- 필드가 기본 타입일 경우 값의 복사가 일어나고, 필드가 참조타입일 경우에는 객체의 번지가 복사 된다.
- Object 클래스의 clone() 메소드를 사용하되, 리턴타입이 Object이므로 적절한 타입으로 형변환하여 사용하도록 한다.
- clone() 메소드는 CloneNotSupportedException 예외 처리를 해 줘야 한다.
Student.java
- Student 클래스는 Cloneable 인터페이스를 구현하도록 했다.
- getStudent() 메소드 내부에서는 Student 객체의 복제가 일어나며, 이렇게 복제된 객체를 리턴한다.
Student cloned = null;
cloned = (Student) clone();
Student cloned = null;
cloned = (Student) clone();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package quiz01_clone;
public class Student implements Cloneable{
//필드
String sno;
String name;
int age;
String dept;
int[] scores;
//생성자
public Student(String sno, String name, int age, String dept, int[] scores) {
this.sno = sno;
this.name = name;
this.age = age;
this.dept = dept;
this.scores = scores;
}
//메소드
public Student getStudent() {
Student cloned = null;
try {
cloned = (Student)clone(); //객체 복사
}catch(CloneNotSupportedException e) {
}
return cloned;
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
복제 객체를 얻은 후 나이와 점수 일부를 변경했다. (#10~#12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package quiz01_clone;
public class StudentExample {
public static void main(String[] args) {
//원본 객체 생성
Student original = new Student("20170328", "김자바", 22, "경영학과", new int[] {100, 90, 80});
//복제 객체 얻은 후 나이와 점수 변경
Student cloned = original.getStudent();
//복제 객체의 필드 출력
System.out.println("복제한 Student 객체의 필드값");
System.out.println();
//원본 객체의 필드 출력
System.out.println("원본 Student 객체의 필드값");
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
출력해보니, 원본 객체의 나이는 그대로이지만 scores[0]의 값이 손상된 것을 볼 수 있다.
이것이 얕은 복제의 한계이다.

얕은 복제를 하게 되면 원본 객체의 필드와 복제 객체의 필드가 같은 객체를 참조하므로, 복제 객체에서 참조 객체를 변경하면 원본 객체도 변경된 객체를 갖게 되어 값이 손상되는 것이다.
그럼 어떡하냐고? 깊은 복제를 하면 된다.
03. 깊은 복제(deep clone)
- 복제될 객체가 참조하고 있는 객체까지 함께 복사한다.
- Object 클래스의 clone() 메소드를 재정의하여 참조 객체를 복사하는 코드를 직접 작성하면 된다.
Employee 객체가 참조하게 될 Car 클래스이다.
1
2
3
4
5
6
7
8
9
10
11
|
package quiz01_clone;
public class Car {
//필드
String model;
public Car (String model) {
this.model = model;
}
}
|
Employee.java
- car와 scores가 깊은 복제 대상이다.
- Object 클래스의 clone() 메소드를 재정의하여 깊은 복제를 한다.
- 이 때, 먼저 얕은 복사를 하기 위해 Object 클래스의 clone 메소드를 먼저 호출해줘야 한다.(#23)
Employee cloned = (Employee)super.clone();
Employee cloned = (Employee)super.clone();
- getEmployee() 메소드에서는 재정의된 clone() 메소드를 호출한다. (#35)
cloned = (Employee)clone();
cloned = (Employee)clone();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package quiz01_clone;
import java.util.Arrays;
public class Employee implements Cloneable{
String eno;
String name;
int age;
int[] scores;
Car car;
public Employee(String eno, String name, int age, int[] scores, Car car) {
this.eno = eno;
this.name = name;
this.age = age;
this.scores = scores;
this.car = car;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//먼저 얕은 복사로 eno, name, age 를 복사한다
Employee cloned = (Employee)super.clone();
//scores 깊은 복제하기
//Car 깊은 복제하기
//리턴
return cloned;
}
public Employee getEmployee() {
Employee cloned = null;
try {
cloned = (Employee)clone();
} catch(CloneNotSupportedException e) {
}
return cloned;
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
아까랑 똑같다. #9~#11만 잘 보면 됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package quiz01_clone;
public class EmployeeExample {
public static void main(String[] args) {
//원본 객체 생성
Employee original = new Employee("20171212", "안성실", 31, new int[] {50, 40, 30}, new Car("소나타"));
//복제 객체를 얻은 후 참조 객체의 값 변경
Employee cloned = original.getEmployee();
//복제 객체의 필드값
System.out.println("복제 객체의 필드값");
System.out.println();
//원본 객체의 필드값
System.out.println("원본 객체의 필드값");
System.out.println();
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
코드를 실행하면 아까와 달리 원본 객체의 scores[0]의 값은 그대로인 것을 볼 수 있다. 물론, 자동차 모델도 마찬가지다.

'IT > Java' 카테고리의 다른 글
18_자바 System 클래스 : exit 메소드, 프로그램 실행 소요 시간 구하기 (0) | 2019.12.20 |
---|---|
17_자바 Objects 클래스 : 객체 비교(Comparator<T>) (0) | 2019.12.20 |
15_자바 예외 처리 : try-with-resources, 사용자 정의 예외 클래스 (0) | 2019.12.13 |
14_자바 예외 : 에러(Error)와 예외(Exception), 자바 예외의 종류 (0) | 2019.12.13 |
13_중첩클래스(Nested Class) : 인스턴스 멤버 클래스, 정적 멤버 클래스, 로컬클래스(메소드 내부에 클래스 만들기) (0) | 2019.12.13 |