์๋ฐ ๊ฐ์ฒด ๋ณต์ฌํ๊ธฐ ( feat. how to use CloneUtils? )
์๋ฐ(Java)๋ก ๊ฐ๋ฐ์ ํ๋ค๋ณด๋ฉด ํ๋ฒ์ฏค ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํ๋ ๋ก์ง์ ์์ฑํ ๋๊ฐ ์๋ค. ๊ทธ๋๋ง๋ค ๋์ค๋ ์ด์ผ๊ธฐ์ธ Shalldow Copy
์ Deep Copy
. ํ๊ตญ์ด๋ก ํํํ๋ฉด ์์ ๋ณต์ฌ์ ๊น์ ๋ณต์ฌ๋ผ๊ณ ์ด์ผ๊ธฐ๋ฅผ ํ๋๋ฐ ์ด ๋ ๊ฐ๋
์ ์ฐจ์ด๋ ์์ฃผ ๊ฐ๋จํ๋ค. ๊ฐ์ฒด์ ์ฃผ์๊ฐ์ ๋ณต์ฌํ๋์ง, ์๋๋ฉด ๊ฐ์ฒด์ ์ค์ ๊ฐ(value)๋ฅผ ๋ณต์ฌํ๋์ง. ์ด ๋์ ์ฐจ์ด์ ์ ์๊ฐํ๋ ๊ธ๋ค์ ์๋ ๋ง์ผ๋ ํจ์คํ๋๋ก ํ๊ณ ์ด๋ฒ ํฌ์คํ
์์๋ Deep Copy
๋ฅผ ํ ๋ org.apache.http.client.utils
ํ์์ ์๋ CloneUtils
์ฌ์ฉ๋ฒ์ ๋ํด ์ ๋ฆฌ ํ๊ณ ์ ํ๋ค.
๊ทธ๋ฅ ์ฐ๋ฉด ๋๋๊ฑฐ ์๋๊ฐ? ๋ผ๊ณ ์๊ฐํ์ง๋ง (๋ณ๊ฑฐ ์๋๋ผ๊ณ ์๊ฐํ์ง๋ง) ํด๋ณด๊ณ ์ํด๋ณด๊ณ ์ ์ฐจ์ด๋ ์์ฒญ์ปธ๊ณ ์ฌ์ฉํ ๋ ์ฃผ์์ ์ด ๋ช๊ฐ์ง ์์ด ์ ๋ฆฌ ํ๋ ค๊ณ ํ๋ค.
์์ ์ ์์ ๋ณธ ํฌ์คํ ์์ ์ฌ์ฉํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋จํ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. (ํ๊ต์์ ํ์ ์ ์์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ค๊ณ ๊ฐ์ ํด๋ณด์.)
public class Student {
String name; // ์ด๋ฆ
int age; // ๋์ด
Family family; // ๊ฐ์กฑ
}
public class Family {
String name; // ์ด๋ฆ
int age; // ๋์ด
boolean isOfficeWorkers; // ์ง์ฅ์ธ ์ฌ๋ถ
}
public class PhysicalInformation {
int height; // ํค
int weight; // ๋ชธ๋ฌด๊ฒ
}
๊ฐ์ฒด๋ Cloneable interface ๋ฅผ implement ํด์ผํ๊ณ clone ๋ฉ์๋๋ฅผ public ์ผ๋ก override ํด์ผํ๋ค.
๋น์ฐํ ์ด์ผ๊ธฐ๊ฐ ๋ ์๋ ์์ผ๋ CloneUtils
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํด๋น ๊ฐ์ฒด๋ Cloneable interface ๋ฅผ implement ํด์ผํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋์ clone ๋ฉ์๋๋ฅผ override ํด์ผ๋๋๋ฐ ์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ์ ์ ์ธ๋ถ์์๋ ํธ์ถ์ด ๊ฐ๋ฅํด์ผํ๊ธฐ ๋๋ฌธ์ public
์ผ๋ก override๋ฅผ ํด์ผํ๋ค. (๊ธฐ๋ณธ์ protected ๋ก ๋์ด์๋ค.) ์ฐ์ ๊ฐ๋จํ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ถ๋ ฅ๋ถํฐ ํด๋ณด์. (์ถ๋ ฅ์ ์ด์๊ฒ ํ๊ธฐ ์ํด ToStringBuilder.reflectionToString
์ ์ฌ์ฉํ์๋ค.)
PhysicalInformation physicalInformation = new PhysicalInformation();
physicalInformation.height = 180;
physicalInformation.weight = 70;
System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));
๊ฒฐ๊ณผ๋ ๋น์ฐํ
PhysicalInformation@5d6f64b1[height=180,weight=70]
์ด์ Cloneable interface ๋ฅผ implement ํ๊ณ clone ๋ฉ์๋๋ฅผ public ์ผ๋ก override ํ๋ค, CloneUtils๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํด๋ณด์. ํ
์คํธ๋ฅผ ํ๋ฉด์ Shalldow Copy
๋ ํด๋ณด์.
// class setting
public class PhysicalInformation implements Cloneable{
int height;
int weight;
@Override
public Object clone() throws CloneNotSupportedException { // public ์ผ๋ก ๋ฐ๊ฟ์ฃผ์.
return super.clone();
}
}
// test code
PhysicalInformation physicalInformation = new PhysicalInformation();
physicalInformation.height = 180;
physicalInformation.weight = 70;
PhysicalInformation physicalInformationShalldowCopy = physicalInformation;
PhysicalInformation physicalInformationDeepCopy = null;
try {
physicalInformationDeepCopy = (PhysicalInformation)CloneUtils.clone(physicalInformation);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// ์๋ณธ
System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));
// ์์ ๋ณต์ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationShalldowCopy, ToStringStyle.DEFAULT_STYLE));
// ๊น์ ๋ณต์ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationDeepCopy, ToStringStyle.DEFAULT_STYLE));
// ๊ฐ ๋ณ๊ฒฝ
physicalInformation.weight = 80;
physicalInformation.height = 170;
// ์๋ณธ
System.out.println(ToStringBuilder.reflectionToString(physicalInformation, ToStringStyle.DEFAULT_STYLE));
// ์์ ๋ณต์ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationShalldowCopy, ToStringStyle.DEFAULT_STYLE));
// ๊น์ ๋ณต์ฌ
System.out.println(ToStringBuilder.reflectionToString(physicalInformationDeepCopy, ToStringStyle.DEFAULT_STYLE));
๊ฒฐ๊ณผ๋ ์๋ณธ๊ณผ ์์ ๋ณต์ฌ๋ฅผ ํ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์(?)๊ฐ ๊ฐ์ผ๋ ๊น์ ๋ณต์ฌ๋ฅผ ํ๊ฒ์ ๋ฐ์ดํฐ๋ ๊ฐ์ง๋ง ์ฃผ์๊ฐ ๋ค๋ฅด๊ณ ๊ฐ์ ๋ณ๊ฒฝํด๋ ์ํฅ์ ์ฃผ์ง ์๋๋ค. (์์ ํ ์๋ก๋ค๋ฅธ ๊ฐ์ฒด์ธ๊ฒ์ ์ฆ๋ช )
PhysicalInformation@1376c05c[height=180,weight=70]
PhysicalInformation@1376c05c[height=180,weight=70]
PhysicalInformation@1b4fb997[height=180,weight=70]
PhysicalInformation@1376c05c[height=170,weight=80]
PhysicalInformation@1376c05c[height=170,weight=80]
PhysicalInformation@1b4fb997[height=180,weight=70]
๋ง์ฝ ์์์ clone์ ๊ธฐ๋ณธ๊ฐ์ธ protected๋ก override๋ฅผ ํ๊ฒ ๋๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ฌ๊น?
Exception in thread "main" java.lang.NoSuchMethodError: com.PhysicalInformation.clone()
at org.apache.http.client.utils.CloneUtils.cloneObject(CloneUtils.java:55)
at org.apache.http.client.utils.CloneUtils.clone(CloneUtils.java:77)
at com.Test.main(Test.java:16)
์ ๊ทผ์ ํ์์์ ๋์น๋ฅผ ์ฑ์๋ ์์๊ฒ ์ง๋ง ์ ๊ทผ์ ํ ์์์ด CloneUtils ์ด ๋ฆฌํ๋ ์ ์ ํ๋ ๊ณผ์ ์์ Exception์ ๋ฐ์ํ๋ค. ๊ผญ! public ์ผ๋ก override๋ฅผ ํด์ฃผ์.
๊ฐ์ฒด ๋ด์ clone์ด ์๋๋ ๋ณ์๋ ๋ณ๋ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
๊ฐ์ฒด ๋ด์ ์๋ ๋ฉค๋ฒ ๋ณ์๋ ์์ ๋ณ์(int, char, float ๋ฑ) , Immutable Class (String, Boolean, Integer ๋ฑ) ๋๋ Enum ํ์์ผ ๋๋ ์๋ณธ์ ๊ฐ์ ๋ฐ๋ก ๋์ ํด๋ ๋์ง๋ง, ๊ทธ๋ ์ง ์์ ๋๋ ๋ฉค๋ฒ๋ณ์์ clone์ ํธ์ถํ์ฌ ๋ณต์ฌํด์ผ ํ๋ค. ๋ง๋ก๋ง ๋ณด๋ฉด ๋ฌด์จ์ด์ผ๊ธฐ ์ธ์ง ๋ชจ๋ฅด๋ ์์ ๋ฅผ ๋ณด์.
public class Student implements Cloneable {
String name;
int age;
Family family;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Student ํด๋์ค์์ Cloneable ๋ฅผ implements ํ๊ณ clone ๋ฉ์๋๋ฅผ override ํ์๋ค. (์ฌ๊ธฐ์ ๊ตฌ๋ฉ์ด ์๋ค!!) ๊ทธ๋ค์ Family ํด๋์ค๋ ์ด๊ธฐ ๊ทธ๋๋ก ๋๊ณ CloneUtils์ ์ฌ์ฉํด์ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํ๋ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์.