[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] Item13. clone ์žฌ์ •์˜๋Š” ์ฃผ์˜ํ•ด์„œ ์ง„ํ–‰ํ•˜๋ผ. (Clone๊ทœ์•ฝ)

2023. 2. 1. 15:09ใ†JAVA/Effective JAVA

728x90

 

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

 

 

Clone() ์ด๋ž€? 

: Object ํด๋ž˜์Šค์˜ clone() ๋ฉ”์„œ๋“œ๋Š” ์ž์‹ ์„ ๋ณต์ œํ•˜์—ฌ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ผ์„ ํ•œ๋‹ค. 

๋‹จ์ˆœํžˆ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์˜ ๊ฐ’๋งŒ ๋ณต์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ์กฐํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค๋Š” ์™„์ „ํ•œ ์ธ์Šคํ„ด์Šค ๋ณต์‚ฌ๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๋Š”๋‹ค. 

 

Clone()์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ณต์ œํ•  ํด๋ž˜์Šค๊ฐ€ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. 

Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋“ค์–ด๊ฐ€๋ณด๋ฉด ์•„๋ฌด๋Ÿฐ ๋‚ด์šฉ์ด ์—†๋Š” ๋นˆ ์ธํ„ฐํŽ˜์ด์Šค์ธ๋ฐ ๊ทธ๋ƒฅ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๋ณต์ œ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค€๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

public class PhoneNumber implements Cloneable{

    private final short areaCode, prefix, lineNum;

    public PhoneNumber(int areaCode, int prefix, int lineNum)
    {
        this.areaCode = rangeCheck(areaCode, 999, "area code");
        this.prefix = rangeCheck(prefix, 999, "prefix");
        this.lineNum = rangeCheck(lineNum, 9999, "line num");
        System.out.println("constructor is called !");
    }

    // toString์ด ๋ฐ˜ํ™˜๋œ ๊ฐ’์— ํฌํ•จ๋œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” API๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
    public short getAreaCode()
    {
        return areaCode;
    }

    public short getPrefix()
    {
        return prefix;
    }

    public short getLineNum()
    {
        return lineNum;
    }

    private static short rangeCheck(int val, int max, String arg)
    {
        if (val < 0 || val > max) {
            throw new IllegalArgumentException(arg + ": " + val);
        }
        return (short) val;
    }

    // PhoneNumber๋ฅผ ๋ฆฌํ„ดํ•˜๋„๋ก ํ•ด์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ๋•Œ ํƒ€์ž… ์บ์ŠคํŒ…์„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    @Override
    public PhoneNumber clone() {
        try {
            return (PhoneNumber) super.clone();
        } catch (CloneNotSupportedException e) { // ์ผ์–ด๋‚  ์ˆ˜ ์—†๋Š” ์ผ์ด๋‹ค.
            throw new AssertionError(); // ๋Œ€์‹  ์—๋Ÿฌ๋ฅผ ๋˜์ ธ์คฌ์Œ
        }
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;
        if (!(o instanceof PhoneNumber)) {
            return false;
        }

        PhoneNumber that = (PhoneNumber) o;
        return areaCode == that.areaCode && prefix == that.prefix && lineNum == that.lineNum;
    }

    @Override
    public int hashCode()
    {
        int result = Short.hashCode(areaCode);
        result = result + 31 * Short.hashCode(prefix);
        result =result +  31 * Short.hashCode(lineNum);

        return result;
    }

    @Override
    public String toString()
    {
        return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
    }

    public static PhoneNumber of(String phoneNumberString)
    {
        String[] split = phoneNumberString.split("-");
        PhoneNumber phoneNumber = new PhoneNumber(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
        return phoneNumber;
    }

}

Clone์„ ์žฌ์ •์˜ํ–ˆ๋Š”๋ฐ IDE์˜ ๋„์›€์œผ๋กœ clone์„ ์žฌ์ •์˜ํ•˜๋ฉด ์ ‘๊ทผ์ œ์–ด์ž๊ฐ€ public ์ด ์•„๋‹Œ protected ์—ฌ์„œ ๋‹ค๋ฅธํด๋ž˜์Šค๊ฐ€ ๋ณต์ œํ•  ๋•Œ clone๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ public์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค. 

 

 

๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด 

phoneNumber.clone()์„ ํ•˜๋ฉด PhoneNumber์„ ์ •์ƒ์ ์œผ๋กœ cloneํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

์œ„์˜ PhoneNumber๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ผ์„œ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , clone() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค. 

(Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด clone์„ ํ•  ์ˆ˜ ์—†๋‹ค.) 

 

โ—๏ธ ๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์œผ๋กœ ๋ฐ˜๋“œ์‹œ super.clone() ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. 

public class Item implements Cloneable {

    private String name;

    // ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค์˜ clone()์ด ๊นจ์งˆ ์ˆ˜ ์žˆ๋‹ค.
    // ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋งŒ๋“ค๋ฉด ์•ˆ๋œ๋‹ค!!!!
    @Override
    public Item clone() {
        Item item = new Item();
        item.name = this.name;
        return item;
    }
  }
public class SubItem extends Item implements Cloneable{

    private String name;

    @Override
    public SubItem clone() {
        return (SubItem) super.clone(); // Item -> SubItem์œผ๋กœ ๋ณ€ํ™˜์„ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ ๋ฐœ์ƒํ•จ..!!
    }

    public static void main(String[] args) {
        SubItem subItem = new SubItem();
        SubItem clone = subItem.clone();

        System.out.println("(clone != null) = " + (clone != null));
        System.out.println("(clone.getClass() == subItem.getClass()) = " + (clone.getClass() == subItem.getClass()));
        System.out.println("clone.equals(subItem) = " + clone.equals(subItem));
    }
}

Item์—์„œ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  clone()์„ ์žฌ์ •์˜ํ•  ๋•Œ , super.clone() ์ด ์•„๋‹Œ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด 

Item์„ ์ƒ์†๋ฐ›์€ SubItem์—์„œ cloneํ•  ๋•Œ, Item์„ subItem์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. 

Exception in thread "main" java.lang.ClassCastException: class chapter02.item13.clone_use_constructor.Item cannot be cast to class chapter02.item13.clone_use_constructor.SubItem (chapter02.item13.clone_use_constructor.Item and chapter02.item13.clone_use_constructor.SubItem are in unnamed module of loader 'app') at chapter02.item13.clone_use_constructor.SubItem.clone(SubItem.java:12) at chapter02.item13.clone_use_constructor.SubItem.main(SubItem.java:17)

 

// ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•œ clone
@Override
public Item clone()  {
    Item result = null;
    try {
        result = (Item) super.clone();
        return result;
    } catch (CloneNotSupportedException e) {
        throw new AssertionError();
    }
}

Item clone์„ super.clone์œผ๋กœ ๋ฐ”๊ฟ”์„œ ๋‹ค์‹œ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์ธ๋ฐ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

 

Clone ๊ทœ์•ฝ 

- x.clone() != x ๋Š” ๋ฐ˜๋“œ์‹œ true์ด๋‹ค. 

- x.clone().getClass() == x.getClass() ๋Š” ๋ฐ˜๋“œ์‹œ true์ด๋‹ค. 

- x.clone().equals(x) ๋Š” ture๊ฐ€ ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค. 

 

-> clone ๊ทœ์•ฝ์„ ๋ณด๋ฉด ์‚ด์ง ์• ๋งค๋ชจํ˜ธํ•˜๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

728x90