Skip to content

Latest commit

ย 

History

History
177 lines (133 loc) ยท 6.22 KB

item13.md

File metadata and controls

177 lines (133 loc) ยท 6.22 KB

Item 13. clone ์žฌ์ •์˜๋Š” ์ฃผ์˜ํ•ด์„œ ์ง„ํ–‰ํ•˜๋ผ

Cloneable ์ธํ„ฐํŽ˜์ด์Šค

  • Cloneable ์ธํ„ฐํŽ˜์ด์Šค ?
    ๋ณต์ œํ•ด๋„ ๋˜๋Š” ํด๋ž˜์Šค์ž„์„ ๋ช…์‹œํ•˜๋Š” ๋ฏน์Šค์ธ ์ธํ„ฐํŽ˜์ด์Šค
๋ฏน์Šค์ธ : ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ๋ถ€๋ชจํด๋ž˜์Šค๊ฐ€ ๋˜์ง€ ์•Š์œผ๋ฉด์„œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํด๋ž˜์Šค
'์ƒ์†' ์ด ์•„๋‹Œ 'ํฌํ•จ'
public interface Cloneable {
}
  • clone() ๋ฉ”์„œ๋“œ ?
java.lang.Object

protected native Object clone() throws CloneNotSupportedException;
  • Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋นˆ ์ธํ„ฐํŽ˜์ด์Šค !
    ๋”ฐ๋ผ์„œ Cloneable ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  clone() ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค.

  • clone() ๋ฉ”์„œ๋“œ๋Š” ๋”ฐ๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•ด์ค˜์•ผ ํ•œ๋‹ค ! ๋˜ clone() ์€ ์ ‘๊ทผ์ œํ•œ์ž๊ฐ€ protected ๋ผ์„œ ๊ฐ™์€ ํŒจํ‚ค์ง€์—์„œ๋งŒ ์ ‘๊ทผ๊ฐ€๋Šฅ.

๊ทธ๋Ÿผ Cloneable ์™œ ์”€ ?

  • clone() ์€ ๋ชจ๋“  ํด๋ž˜์Šค์—์„œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ•˜์ง€๋งŒ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ ํด๋ž˜์Šค์˜ clone() ์€ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค !!

  • super.clone() ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฑฐ๋ผ๋ฉด, Cloneable ํ•„์š” ์—†์Œ.

  • Cloneable ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋งŒ clone() ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • clone() ์€ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค.

  • ๋”ฐ๋ผ์„œ Cloneable ์€ ์ƒ์œ„ ํด๋ž˜์Šค (Object) ์— ์ •์˜๋œ clone() ์˜ ๋™์ž‘๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

๋ฌธ์ œ์  ?

clone ์˜ ํ—ˆ์ˆ ํ•œ ๊ทœ์•ฝ

1. x.clone() != x // ๋ณต์‚ฌํ•œ ๊ฐ์ฒด๋Š” ์›๋ณธ ๊ฐ์ฒด์™€ ๋…๋ฆฝ์ ์ž„.
2. x.clone().getClass() == x.getClass(); // ๋ณต์‚ฌํ•œ ๊ฐ์ฒด์™€ ์›๋ณธ ๊ฐ์ฒด๋Š” ๊ฐ™์€ ํด๋ž˜์Šค์ž„.
3. x.clone().equals(x)
๊ด€๋ก€์ƒ, clone() ์€ super.clone() ์„ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์–ป์–ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์œ„ ์กฐ๊ฑด์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹Œ์„ ํƒ
  1. ์ƒ์„ฑ์ž ์—ฐ์‡„
  • ์–ด๋–ค ํด๋ž˜์Šค์—์„œ clone() ์„ new ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ๋ณต์‚ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์žฌ์ •์˜ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

  • ์ด ์žฌ์ •์˜๋Š” ์ปดํŒŒ์ผ์ƒ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.

  • ํ•˜์ง€๋งŒ ๊ทธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ํด๋ž˜์Šค์—์„œ super.clone() ์„ ํ•œ๋‹ค๋ฉด, ํ•˜์œ„ ํด๋ž˜์Šค์˜ ํƒ€์ž…์ด ์•„๋‹Œ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ํด๋ž˜์Šค๊ฐ€ final ์ด๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์—†์œผ๋‹ˆ new ๋ฅผ ์จ๋„ ๊ดœ์ฐฎ๋‹ค. (ํ•˜์ง€๋งŒ Cloneable ๊ตฌํ˜„์ด์œ ๋„ ์—†๋‹ค)

ํ•ด๊ฒฐ๋ฒ•

ํด๋ž˜์Šค์˜ ํ•„๋“œ๊ฐ€ ๋ชจ๋‘ ๋ถˆ๋ณ€์ด๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ํ•˜๋ฉด ๋œ๋‹ค.

  • super.clone() ํ˜ธ์ถœ
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ˜•๋ณ€ํ™˜์„ ํ•  ํ•„์š”์—†๊ฒŒ ๊ณต๋ณ€ ๋ณ€ํ™˜ ํƒ€์ดํ•‘์„ ์ ์šฉ
  • ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜

๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ•„๋“œ๊ฐ€ ์•˜๋‹ค๋ฉด ?

๊ฐ€๋ณ€ ํ•„๋“œ๋ฅผ super.clone() ์œผ๋กœ ๋ณต์ œํ•ด๋ฒ„๋ฆฌ๋ฉด,
๊ฐ’์„ ๋ณต์ œํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ฃผ์†Œ๊ฐ’์„ ๋ณต์‚ฌํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

clone ์€ ์›๋ณธ ๊ฐ์ฒด์— ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๋Š” ๋™์‹œ์— ๋ณต์ œ๋œ ๊ฐ์ฒด์˜ ๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•ด์•ผ ํ•œ๋‹ค.
clone() ์—์„œ ์žฌ๊ท€์ ์œผ๋กœ ๊ฐ€๋ณ€ ๊ฐ์ฒด ์ฐธ์กฐ ํ•„๋“œ๋ฅผ ๋ณต์‚ฌํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ๊ฐ€๋ณ€ ์ฐธ์กฐ ํ•„๋“œ๊ฐ€ final ์ด๋ผ๋ฉด ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ฐธ์กฐํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์œ„์˜ ๋ฐฉ์‹์„ ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ•„๋“œ๋Š” final ๋กœ ์„ ์–ธํ•˜๋ผ ๋ผ๋Š” ์šฉ๋ฒ•๊ณผ ์ถฉ๋Œํ•˜๊ฒŒ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ Cloneable ์„ ๊ตฌํ˜„ํ•˜๋ฉด final ์„ ๋•Œ๋ฒ„๋ ค์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

clone() ์žฌ๊ท€ ํ˜ธ์ถœ์ด ๋ถ€์กฑํ•˜๋‹ค๋ฉด Deep copy ๋ฅผ ํ•˜๋ผ

๋งŒ์•ฝ ๋ฐฐ์—ด ์•ˆ์— ๊ฐ€๋ณ€ ์ฐธ์กฐ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋ฉด?

์žฌ๊ท€์ ์ธ clone() ํ˜ธ์ถœ์œผ๋กœ๋Š” ๋ถ€์กฑํ•˜๋‹ค.

๊ทธ๋Ÿด๋•Œ๋Š” Deep copy ๋ฅผ ํ•œ๋‹ค.

    public Entry deepCopy() {
        return new Entry(key, value, next == null ? null : next.deepCopy());
    }
    @Override
    public CustomHashTable clone() {
        try {
            CustomHashTable result = (CustomHashTable) super.clone();
            result.buckets = new Entry[buckets.length];

            for (int i = 0; i < buckets.length; i++) {
                if (buckets[i] != null)
                    result.buckets[i] = buckets[i].deepCopy();
            }

            return result;
        } catch (final CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

์ด ๋ฐฉ์‹์€ ์›์†Œ ์ˆ˜๋งŒํผ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค.
๋”ฐ๋ผ์„œ ์›์†Œ ์ˆ˜๋งŒํผ์˜ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์†Œ๋น„ํ•˜๊ณ , ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿด๋• ๋ฐ˜๋ณต์ž๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

    public Entry deepCopy() {
        Entry result = new Entry(key, value, next);
        for (Entry p = result; p.next != null; p = p.next) {
            p.next = new Entry(p.next.key, p.next.value, p.next.next);
        }
        return result;
    }

๊ณ ์ˆ˜์ค€ API ๋ฅผ ์ด์šฉํ•œ ๊ฐ€๋ณ€๊ฐ์ฒด ๋ณต์ œ

  • Collection ์˜ put, add ๊ฐ™์€ API ๋ฅผ ์ด์šฉํ•˜์—ฌ ์š”์†Œ๋ฅผ ๋ณต์ œ
  • ์ƒ๋Œ€์ ์œผ๋กœ ๋Š๋ฆฌ๋‹ค.

clone()์—์„œ๋Š” ์žฌ์ •์˜ ๋  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

  • ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์“ธ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.

clone() ๋ฅผ ์žฌ์ •์˜ ํ•  ๋•Œ์—๋Š” public ์ ‘๊ทผ์ž, throw ๋˜์ง€์ง€ ์•Š๊ธฐ

  • public ์ด์–ด์•ผ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์‰ฝ๋‹ค.
  • throw ๋ฅผ ๋˜์ง€๋Š” ๊ฒƒ์„ ๊ณ„์† ์ •์˜ํ•˜๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค์—๋„ ๊ณ„์† try-catch ๋ฅผ ์จ์ค˜์•ผ ํ•œ๋‹ค.

์š”์•ฝ

  1. Cloneable ์„ ๊ตฌํ˜„ํ•˜๋ฉด, clone() ์„ ์žฌ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.
  2. ์ ‘๊ทผ์ž๋Š” public, ๋ฐ˜ํ™˜ํ˜•์€ ์ž๊ธฐ์ž์‹ ์˜ ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
  3. ๊ณต๋ณ€ ๋ณ€ํ™˜ ํƒ€์ดํ•‘์„ ํ†ตํ•ด ์ž๊ธฐ์ž์‹ ์˜ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  4. super.clone() ์œผ๋กœ ๋ณต์ œ ํ•œ๋‹ค.
  5. ๊นŠ์€ ๋ณต์ œ ๋ฐฉ์‹์œผ๋กœ ๊ฐ€๋ณ€ ์ฐธ์กฐ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค.

๊ฒฐ๋ก  : ๋ณต์ œ๋Š” ๊ทธ๋ƒฅ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์™€ ๋ณต์‚ฌ ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์จ๋ผ

๋ฐฐ์—ด๋งŒ์ด clone() ์„ ์žฌ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ผํ•œ ์˜ˆ์ด๋‹ค. ๋ณต์‚ฌํ•˜๋Š” ๋Œ€์ƒ์ด ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ฉด ๋ณต์‚ฌ ์ƒ์„ฑ์ž, ๋ณต์‚ฌ ํŒฉํ„ฐ๋ฆฌ๊ฐ€ ์ข‹๋‹ค.

๋ณต์‚ฌ ์ƒ์„ฑ์ž

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack(Stack s) {
        this.elements = s.elements.clone();
        this.size = s.size;
    }
}

๊ธฐ๋ณธ ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์ถ”๊ฐ€ํ•˜๊ธฐ

๋ณต์‚ฌ ํŒฉํ„ฐ๋ฆฌ

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public static Stack newInstance(Stack s) {
        return new Stack(s.elements, s.size);
    }
}