Item 13. clone
clone ์ฌ์ ์๋ ์ฃผ์ํด์ ์งํํ๋ผ
Cloneable
public interface Cloneable {
// ์ด๋ค ๊ตฌํ๋ ๋์ด ์์ง ์์
}
Cloneable์ ๋ณต์ ํด๋ ๋๋ ํด๋์ค์์ ๋ช ์ํ๊ธฐ ์ํ ์ธํฐํ์ด์ค์ด๋ค. ํ์ง๋ง ์๋์๋ ๋ค๋ฅด๊ฒ ํด๋น ๋ชฉ์ ์ ์ ๋๋ก ์ํํ์ง ๋ชปํ๊ณ ์๋๋ฐ, ๊ทธ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค.
clone ๋ฉ์๋๊ฐ ์ ์ธ๋ ๊ณณ์ด Cloneable์ด ์๋ Object์ protected๋ก ์ ์ธ๋์ด ์์
๋๋ฌธ์ ๋น์ด์๋ Cloneable์ ๊ตฌํํด๋ clone ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์
์ด์ฒ๋ผ ๋ฌธ์ ๊ฐ ๋ง์ ์ธํฐํ์ด์ค์ง๋ง ํด๋น ๋ฐฉ์์ ๋๋ฆฌ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์, ์์๋๋ ๊ฒ์ด ์ข๋ค.
Cloneable ์ธํฐํ์ด์ค์ ์ญํ
๋ด๋ถ ๊ตฌํ์ด ์๋ฌด๊ฒ๋ ์์ง๋ง Object์ protected ๋ฉ์๋์ธ clone์ ๋์ ๋ฐฉ์์ ๊ฒฐ์ ํ๋ค. Cloneable์ ๊ตฌํํ ํด๋์ค์ ์ธ์คํด์ค์์ clone ํธ์ถํ๋ฉด ํด๋น ๊ฐ์ฒด์ ํ๋๋ค์ ํ๋ํ๋ ๋ณต์ฌํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , Cloneable์ ๊ตฌํํ์ง ์์ ํด๋์ค์ ์ธ์คํด์ค์์ clone ํธ์ถํ๋ฉด CloneNotSupportedException์ ๋์ง๋ค.
class NotCloneable {
int x;
int y;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Cloneable implements java.lang.Cloneable {
int x;
int y;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Cloneable cloneable = new Cloneable();
NotCloneable notCloneable = new NotCloneable();
cloneable.clone(); // OK
notCloneable.clone(); // CloneNotSupportedException
}
}
์ธํฐํ์ด์ค๋ฅผ ์๋นํ ์ด๋ก์ ์ผ๋ก ์ฌ์ฉํ ์ฌ๋ก๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๊ณณ์ ์ด๋ฌํ ๋ฐฉ์์ ์ ์ฉํ๋ ๊ฒ์ ์ข์ง ์๋ค. (์ผ๋ฐ์ ์ผ๋ก ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ํด๋น ์ธํฐํ์ด์ค์์ ์ ์ ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๊ฒ์ด์ง๋ง, ์ด ๊ฒฝ์ฐ์ ์์ ํด๋์ค์ ์ ์๋ ๋์ ๋ฐฉ์์ ๊ฒฐ์ ํ๋ค.)
Object.clone
clone ๋ฉ์๋์ ๊ท์ฝ์ ํ์ ํ ํธ์ธ๋ฐ, Object ๋ช ์ธ์ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ฆฌ๋์ด ์๋ค.
๊ฐ์ฒด์ ๋ณต์ฌ๋ณธ์ ์์ฑํด ๋ฐํ
๋ณต์ฌ์ ์ ํํ ๋ป์ ๊ทธ ๊ฐ์ฒด๋ฅผ ๊ตฌํํ ํด๋์ค์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์์
์ผ๋ฐ์ ์ธ ์๋๋ ๋ค์๊ณผ ๊ฐ์(๋ฐ๋์ ์ด๋ ๊ฒ ๊ตฌํํด์ผ ํ๋ ๊ฒ์ ์๋)
x.clone() != x
x.clone().getClass() == x.getClass()
x.clone().equals(x)
์ฌ๋ฐ๋ฅธ Cloneable ๊ตฌํ ๋ฐฉ๋ฒ
class Point implements Cloneable {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public Point clone() {
try {
return (Point) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // ์ผ์ด๋์ง ์๋ ์๋ฌ, ์ธ๋ถ๋ก ๋์ง์ง ์๋ ๊ฒ์ด ์ข์
}
}
}
clone ๋ฉ์๋๋ฅผ public์ผ๋ก ์ ๊ณตํ๊ณ , super.clone์ ํธ์ถํ ํ ๋ฐํ ํ์ ์ ํด๋น ํด๋์ค๋ก ์บ์คํ ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ ํ์ ์ด๊ฑฐ๋ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋์ ๋ํด์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง, ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋์ ๋ํด์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋๊ฐ ์๋ ํด๋์ค์ clone
Stack ํด๋์ค์ฒ๋ผ ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋๊ฐ ์๋ ํด๋์ค๋ฅผ ์ ๋ฐฉ์์ฒ๋ผ ๊ทธ๋๋ก ๋ณต์ฌ๋ฅผ ํ๊ฒ ๋๋ฉด, ๋ด๋ถ ์์๋ค๊น์ง ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ค.
public class Stack implements Cloneable {
private Object[] elements; // ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋, ๊ทธ๋๋ก ๋ณต์ฌํ๋ฉด ๋ด๋ถ ์์๋ค๊น์ง ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ฒ ๋จ
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
// ...
}
๋๋ฌธ์ ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํด๋์ค๋ผ๋ฉด clone ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ ๋ ํด๋น ํ๋๋ค์ ์๋ก ๋ณต์ฌํด์ ์ฐธ์กฐํ๋๋ก ํด์ผ ํ๋ค.
public class Stack implements Cloneable {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
@Override
public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone(); // ๊ฐ๋ณ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋ณต์ฌ
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
// ...
}
ํ์ง๋ง ์ด ๋ฐฉ๋ฒ์๋ ๋ฌธ์ ๊ฐ ์์ ์ ์๋๋ฐ, ๋ง์ฝ elements๊ฐ final์ด๋ผ๋ฉด ์๋ก์ด ๊ฐ์ ํ ๋นํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฌธ๋ฒ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋์ ๋ณต์ ํ ์ ์๋ ํด๋์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ผ๋ถ ํ๋์์ final์ ์ ๊ฑฐํด์ผ ํ ์๋ ์๋ค. ์ถ๊ฐ์ ์ผ๋ก ๊ฐ๋ณ ๊ฐ์ฒด ๋ด๋ถ์ ๋ ๋ค๋ฅธ ๊ฐ๋ณ ๊ฐ์ฒด๊ฐ ์กด์ฌํ๋ค๋ฉด, ํด๋น ๊ฐ์ฒด๋ค๋ ์ฌ๊ท์ ์ผ๋ก ๋ณต์ฌํด์ผ ํจ์ ์์ง ๋ง์์ผ ํ๋ค.
๊ฒฐ๋ก
clone ๋ฉ์๋๋ ๋ณต์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ์ํด ๊ณ ์๋ ๊ฒ์ด์ง๋ง ์ธ์ด ๋ชจ์์ ์ด๊ณ , ์์ฑํ๊ฒ ๋ฌธ์ํ๋ ๊ท์ฝ, ์์ธ ๋ฐ์ ๊ฐ๋ฅ์ฑ ๋ฑ ๋ฌธ์ ๊ฐ ๋ง๋ค. ์ด๋ฏธ Cloneable์ ๊ตฌํํ ํด๋์ค๋ฅผ ํ์ฅํ๋ ๊ฒ์ด ์๋๋ผ๋ฉด ๋ณต์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํด์ , ๋ณต์ฌ ์์ฑ์๋ ๋ณต์ฌ ํฉํฐ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข๋ค.
Last updated
Was this helpful?