객체를 복사하려면 복사하려는 객체에 Cloneable 인터페이스를 implement 하고 Object 객체의
clone 메서드를 override 해야 합니다. 하지만 단일 클래스일 경우는 괜찮지만
슈퍼 클래스-자식 클래스 와 같이 상속 구조의 클래스 형태는 고려해야 할 사항이
많습니다. 심지어는 복사의 기술적 매커니즘은 자바 기술 밖이라고 합니다.
왜그런지는 설명하기도 어렵고 이해하기도 어렵습니다. 즉 복사를 하려고 했을때
고려해야 할 사항이 너무 많습니다.
그래서 추천하는 복사 방법은 "copy construction" 이란 방법 입니다.
책에는 예제가 없어서 제가 외국 사이트에서 소스 얻어서 재구성 했습니다.
Super Class
import java.util.ArrayList;
import java.util.List;
public class Dog {
private final List names;
private int age;
private int weight;
private String str;
private String values[] = new String[2];
public Dog() {
names = new ArrayList();
}
protected Dog(Dog original) {
names = new ArrayList(original.names);
age = original.age;
weight = original.weight;
str = original.str;
System.arraycopy(original.values, 0, values, 0, original.values.length);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String[] getValues() {
return values;
}
public void setValues(String[] values) {
this.values = values;
}
public List getNames() {
return names;
}
public Dog copy() {
return new Dog(this);
}
}
Child Class
public class Dalmatian extends Dog {
private int spots;
public Dalmatian() {
}
protected Dalmatian(Dalmatian original) {
super(original);
spots = original.spots;
}
public Dalmatian copy() {
return new Dalmatian(this);
}
public static void main(String[] ar) throws Exception {
Dalmatian dalmatian1;
Dalmatian dalmatian2;
String temp;
// 복사 source 클래스 셋팅
dalmatian1 = new Dalmatian();
dalmatian1.setAge(1);
dalmatian1.setStr("00000");
dalmatian1.getNames().add("xxxxx");
dalmatian1.getNames().add("yyyyy");
dalmatian1.getValues()[0] = "----------------";
// target 클래스 복사
dalmatian2 = dalmatian1.copy();
// 복사된 내용 확인 하기
System.out.println("= copy description =========");
System.out.println("copy age ==> " + dalmatian2.getAge());
System.out.println("copy str ==> " + dalmatian2.getStr());
System.out.println("copy names ");
for (int i = 0; i < dalmatian1.getNames().size(); i++) {
temp = (String) dalmatian1.getNames().get(i);
System.out.println(temp);
}
System.out.println("copy values == ");
System.out.println(dalmatian1.getValues()[0]);
System.out.println("= copy description =========");
System.out.println();
// 값은 메모리 주소를 사용하는지 값 과 hashcode 비교
System.out.println("= change value =========");
dalmatian2.setAge(2);
System.out.println("=age1 ==> " + dalmatian1.getAge());
System.out.println("=age2 ==> " + dalmatian2.getAge());
System.out.println();
dalmatian2.setStr("11111");
System.out.println("=str1 ==> " + dalmatian1.getStr());
System.out.println("=str2 ==> " + dalmatian2.getStr());
System.out.println("=str1 hc ==> " + dalmatian1.getStr().hashCode());
System.out.println("=str2 hc ==> " + dalmatian2.getStr().hashCode());
System.out.println();
dalmatian2.getNames().add("wwwww");
dalmatian2.getNames().add("zzzzz");
System.out.println("=names1 ");
for (int i = 0; i < dalmatian1.getNames().size(); i++) {
temp = (String) dalmatian1.getNames().get(i);
System.out.println(temp);
}
System.out.println("=names2 ");
for (int i = 0; i < dalmatian2.getNames().size(); i++) {
temp = (String) dalmatian2.getNames().get(i);
System.out.println(temp);
}
System.out.println("=names1 hc ==> " + dalmatian1.getStr().hashCode());
System.out.println("=names2 hc ==> " + dalmatian2.getStr().hashCode());
System.out.println();
dalmatian2.getValues()[0] = "====================";
System.out.println("=value1[0] ==> " + dalmatian1.getValues()[0]);
System.out.println("=value2[0] ==> " + dalmatian2.getValues()[0]);
System.out.println("=value1 hc ==> "
+ dalmatian1.getValues().hashCode());
System.out.println("=value2 hc ==> "
+ dalmatian2.getValues().hashCode());
System.out.println("= change value =========");
}
}
== Result OUT ==
= copy description =========
copy age ==> 1
copy str ==> 00000
copy names
xxxxx
yyyyy
copy values ==
----------------
= copy description =========
= change value =========
=age1 ==> 1
=age2 ==> 2
=str1 ==> 00000
=str2 ==> 11111
=str1 hc ==> 45806640
=str2 hc ==> 46760945
=names1
xxxxx
yyyyy
=names2
xxxxx
yyyyy
wwwww
zzzzz
=names1 hc ==> 45806640
=names2 hc ==> 46760945
=value1[0] ==> ----------------
=value2[0] ==> ====================
=value1 hc ==> 7699183
=value2 hc ==> 14285251
= change value =========
소스가 좀 기네요 public static void main 함수는 분석 하시지 마세요. ^^ 바로 Resut OUT을 보시면서 이해
하시면 될 것 같습니다.
여기서 중요한 건 슈퍼 클래스 생성자 함수 인데 배열은 값 복사가 메모리 주소 참조값을 그대로 복사하기
때 문에 반드시 "System.arraycopy(original.values, 0, values, 0, original.values.length);" 사용해서
deep copy를 해야 합니다.
객체 복사는 prototype 디자인 패턴에서도 사용하며, 실제 개발을 하다 보면 clone이 필요한 경우가
있습니다. 참고 하시기 바랍니다.
댓글 없음:
댓글 쓰기