์ด๋ฒ ๊ธ์์๋ clone์ ์ฌ์ ์ ํ ๋ ์ด๋ค ์ ์ ์ฃผ์ํด์ ์ฌ์ ์ ํด์ผ ํ๋์ง ์์๋ณด๊ณ ์ ํ๋ค. clone์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฐฉ๋ฒ๋ณด๋ค๋ ์ฃผ์์ ์ ์ด์ ์ด ๋ง์ถฐ์ ธ ์์ผ๋ฏ๋ก clone์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฐฉ๋ฒ์ ์๊ณ ์ถ๋ค๋ฉด ์ด์ ๊ธ์ ์ฐธ๊ณ ํ๊ธฐ ๋ฐ๋๋ค.
clone์ ์ฌ์ ์ํ ๋ ํฌ๊ฒ 2๊ฐ์ง ์ํฉ์ผ๋ก ๊ตฌ๋ถํ ์ ์๋ค. ์ฒซ ๋ฒ์งธ๋ ๋ถ๋ณ ๊ฐ์ฒด์์์ clone์ด๊ณ ๋ ๋ฒ์งธ๋ ๊ฐ๋ณ ๊ฐ์ฒด์์์ clone์ด๋ค.
๋จผ์ ๋ถ๋ณ ๊ฐ์ฒด์ clone์ ์ฌ์ ์ํ ๋ ์ฃผ์์ ์ ์ดํด๋ณด๊ณ , ๋ค์ ๊ธ์ ํตํด ๊ฐ๋ณ ๊ฐ์ฒด์ clone์ ์ฌ์ ์ํ ๋ ์ฃผ์์ ์ ์ดํด๋ณด๋๋ก ํ์.
1. clone ๊ท์ฝ ๐ฉ๐พ
clone์ ์ค๋ฒ๋ผ์ด๋ฉํด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ํด๋์ค์ ์ฌ์ ์๋ฅผ ํ ๋ ๋ค์๊ณผ ๊ฐ์ ์กฐ๊ฑด(๊ท์ฝ)์ ๋ง์กฑํ๊ฒ ๋ง๋ค์ด์ผ ํ๋ค. ์๋์ 3๊ฐ์ง ๊ท์ฝ์ ๊ธฐ์ตํ๊ณ ์ด๋ป๊ฒ ๊ท์ฝ์ ์งํค๋ฉด์ clone์ ์ฌ์ ์ ํ๋์ง ์์๋ณด๋๋ก ํ์.
- x.clone() != x
clone์ผ๋ก ์ป์ ์ธ์คํด์ค๋ ์๋ณธ๊ณผ๋ ๋ค๋ฅธ ์ธ์คํด์ค์ฌ์ผ ํ๋ค.
์ฆ, ์ฐธ์กฐ๊ฐ์ด ๋ฌ๋ผ์ผ ํ๋ค. - x.clone().getClass() == x.getClass()
์๋ณธ๊ณผ ๋์ผํ ํด๋์ค์ฌ์ผ ํ๋ค. - x.clone().equals(x) → ์ผ๋ฐ์ ์ผ๋ก๋ true์ด์ง๋ง ํ์๋ ์๋๋ค!
๊ฐ์ด ๋ค๋ฅผ ์๋ ์๋ ์ด์ ๋ ์ ์ผํ ์๋ณ์(id ๋ฑ๋ฑ)์ ๊ฐ์ด ๋ฌ๋ผ์ ธ์ผ ํ๋ ์ธ์คํด์ค ๊ฐ์ด ์๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
2. ๋ถ๋ณ ๊ฐ์ฒด์์์ clone ๐จ๐ณ
public class User implements Cloneable {
private final String name;
private final int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public User clone() {
try {
return (User) super.clone();
}catch(CloneNotSupportedException e) {
throw new AssertionError(); // ์ผ์ด๋ ์ ์๋ ์ผ์ด๋ค.
}
}
}
๊ธฐ๋ณธ์ ์ผ๋ก clone์ ์ฌ์ ์ํ๋ ๋ฐฉ์์ ์์ ๊ฐ๋ค. ์ด๋ ์๋์ ๊ฐ์ด super.clone()์ ์ฌ์ฉํ๋ ๊ฒ ์๋๋ผ ์์ฑ์๋ฅผ ์ด์ฉํด์ ๊ตฌํํด๋ ๋์ง ์์๊น๋ผ๋ ์๊ฐ์ ํ ์ ์๋ค.
public class User implements Cloneable {
private final String name;
private final int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public User clone() {
User result = new User(this.name, this.age);
return result;
}
}
์ด๋ ๊ฒ ํ๋ฉด ํฐ ๋ฌธ์ ์ ์ด ์๊ธฐ๊ฒ ๋๋ค. User๋ฅผ ์์ํด์ ์ฌ์ฉํ๋ SubUser๊ฐ ์๋ค๊ณ ํ์. SubUser์์๋ clone()์ ์๋์ ๊ฐ์ด ๊ตฌํํ๊ฒ ๋๋ค๋ฉด ClassCastException์ด ๋ฐ์ํ๊ฒ ๋๋ค.
public class SubUser extends User implements Cloneable {
public SubUser(String name, int age) {
super(name, age);
}
@Override
public SubUser clone() {
return (SubUser) super.clone();
}
}
----------
public static void main(String[] args) {
SubUser subUserOrigin = new SubUser("amenable", 24);
SubUser subUserCopy = subUserOrigin.clone(); // ClassCastException
}
๊ทธ ์ด์ ๋ super.clone()์ผ๋ก ์ป๊ฒ ๋๋ ๊ฐ์ ํ์ ์ด ๋น๊ฒฐ์ ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค!
ํธ์ถ๋๋ ๊ณณ์ ํ์ ์ผ๋ก super.clone()์ ํ์ ์ด ๊ฒฐ์ ๋๋ค. ์ฆ, ์ด๋์ ํธ์ถ๋๋๋์ ๋ฐ๋ผ์ super.clone()์ ํ์ ์ด ๊ฒฐ์ ๋๋ค๋ ๊ฒ์ด๋ค.
User ํด๋์ค์ clone์ ํธ์ถํ๋ฉด super.clone์ ํ์ ์ User์ด๊ณ , SubUser ํด๋์ค์ clone์ ํธ์ถํ๋ฉด super.clone()์ผ ํ์ ์ด SubUser๊ฐ ๋๋ค. ์๋์ ์ฝ๋์์ ์ป๊ฒ ๋๋ ํ์ ์ ๋ณธ๋ค๋ฉด ์ฝ๊ฒ ์ดํดํ ์ ์๋ค. (๊ฐ ํด๋์ค์์์ ์ถ๋ ฅ๋ฌธ์ ์ฐธ๊ณ ํ์)
// ์์ฑ์๋ฅผ ์ด์ฉํด์ clone์ ๊ตฌํํ ๊ฒฝ์ฐ
// User์ clone์ ํธ์ถํ๋ ๊ฒฝ์ฐ
public class User implements Cloneable {
private final String name;
private final int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public User clone() {
User result = new User(this.name, this.age);
System.out.println(result.getClass()); // class User
return result;
}
}
----------
public class SubUser extends User implements Cloneable {
public SubUser(String name, int age) {
super(name, age);
}
@Override
public SubUser clone() {
System.out.println(super.clone().getClass()); // class User
return (SubUser) super.clone();
}
}
----------
public static void main(String[] args) {
User userOrigin = new User("amenable", 24);
User userCopy = userOrigin.clone();
}
// ์์ฑ์๋ฅผ ์ด์ฉํด์ clone์ ๊ตฌํํ ๊ฒฝ์ฐ
// SubUser์ clone์ ํธ์ถํ๋ ๊ฒฝ์ฐ
public class User implements Cloneable {
private final String name;
private final int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public User clone() {
User result = new User(this.name, this.age);
System.out.println(result.getClass()); // class SubUser
return result;
}
}
----------
public class SubUser extends User implements Cloneable {
public SubUser(String name, int age) {
super(name, age);
}
@Override
public SubUser clone() {
System.out.println(super.clone().getClass()); // class SubUser
return (SubUser) super.clone();
}
}
----------
public static void main(String[] args) {
SubUser subUserOrigin = new SubUser("amenable", 24);
SubUser subUserCopy = subUserOrigin.clone(); // ClassCastException
}
๊ณต๋ณ ๋ฐํํ์ ์ ์ด์ฉํ๋ค๋ฉด ClassCastException์ด ๋จ์ง ์์์ผ ํ๋ค๊ณ ์๊ฐํ ์ ์๋ค. ๊ณต๋ณ ๋ฐํํ์ ์ด๋ '์ฌ์ ์ํ ๋ฉ์๋์ ๋ฐํ ํ์ ์ ์์ ํด๋์ค์ ๋ฉ์๋๊ฐ ๋ฐํํ๋ ํ์ ์ ํ์ ํ์ ์ด ๋ ์ ์๋ค'๋ ๊ฒ์ด๋ค. ์ฆ, ๋ฐํ ํ์ ์ ํ์ ํ์ ์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค๋ ๊ฒ์ด์ง, ์ค๋ฒ๋ผ์ด๋ฉ ํ ๋ ์์ ํ์ ์ ํ์ ํ์ ์ผ๋ก ๋ณํํด์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด ์๋๋ค.
๋ณธ๋ก ์ผ๋ก ๋์์์ ๋ง์ฝ ์์ฑ์๋ฅผ ์ฌ์ฉํด์ clone์ ๊ตฌํํ๊ฒ ๋๋ค๋ฉด ํด๋น ํด๋์ค์ clone์ ์ฌ์ ์ํ๋ ์์ํด๋์ค(SubUser)์์๋ super.clone()์ผ๋ก ์์ ํ์ (User)์ ๋ฐ๊ณ ๊ทธ๊ฒ์ ๋ค์ ํ์ ํ์ (User → SubUser)์ผ๋ก ๋ณ๊ฒฝ์ ํ๋ ์ํฉ์ด ๋ฐ์ํ๊ฒ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ํฉ์์ ๋น์ฐํ ClassCastException์ด ๋ฐ์ํ๋ค.
(ํ์ ํ์
์ ์์ ํ์
์ผ๋ก ๋ณํํด์ ์ฌ์ฉํ ์ ์์ง๋ง, ์์ ํ์
์ ํ์ ํ์
์ผ๋ก ๋ณํํด์ ์ฌ์ฉํ ์ ์๋ค)
๊ทธ๋ฌ๋ฏ๋ก clone์ ์ฌ์ ์ ํ ๋๋ super.clone()์ ์ฌ์ฉํ๋๋ก ํ์!
๋ค์ ๊ธ์ ํตํด ๊ฐ๋ณ ๊ฐ์ฒด์์๋ clone์ ์ด๋ป๊ฒ ์ ์ํด์ผ ํ๋์ง ๊ณ์ํด์ ์์๋ณด๋๋ก ํ์.
ํด๋น ๊ธ์ ๋ฐฑ๊ธฐ์ ๋์ '์ดํํฐ๋ธ ์๋ฐ ์๋ฒฝ ๊ณต๋ต'์ ์๊ฐํ๊ณ ์์ฑํ ๊ฒ์ ๋๋ค.