Skip to content

Latest commit

ย 

History

History
334 lines (253 loc) ยท 11 KB

README.md

File metadata and controls

334 lines (253 loc) ยท 11 KB

01. ๊นŠ์€ ๋ณต์‚ฌ vs ์–•์€ ๋ณต์‚ฌ ์ฐจ์ด?

๐Ÿ‘ ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” Java์˜ ๊นŠ์€ ๋ณต์‚ฌ ๊ทธ๋ฆฌ๊ณ  ์–•์€ ๋ณต์‚ฌ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

01-1. ๊นŠ์€ ๋ณต์‚ฌ์™€ ์–•์€ ๋ณต์‚ฌ๋ž€?

์–•์€ ๋ณต์‚ฌ์™€ ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์ด์œ ๋Š” primitive type(int, short..)์˜ ๊ฒฝ์šฐ๋Š” ์–•์€ ๋ณต์‚ฌ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ,
reference type(Array, object..)์€ ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ๊ฐ์ฒด์˜ ์‹ค์ œ ๋ฐ์ดํ„ฐ ์ €์žฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ๊นŠ์€ ๋ณต์‚ฌ: ๋ฉ”๋ชจ๋ฆฌ(memory) ์ƒ์— ์ƒˆ๋กœ์šด ๊ณต๊ฐ„์„ ํ• ๋‹นํ•˜๊ณ  ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ
  • ์–•์€ ๋ณต์‚ฌ: ๊ธฐ์กด A ๊ฐ์ฒด๊ฐ€ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ(memory)์˜ ์ฃผ์†Œ๊ฐ’(reference value)๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ

๐Ÿค” ๊ทธ๋Ÿฌ๋ฉด ํ•ด๋‹น ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ๋Š” ์ •๋ฆฌ๋ฅผ ํ–ˆ์œผ๋‹ˆ ์†Œ์Šค ๋ ˆ๋ฒจ์—์„œ 2๊ฐ€์ง€์˜ ์ฐจ์ด์ ์„ ํ•œ๋ฒˆ ๋ณด์ž

01-2. ์–•์€ ๋ณต์‚ฌ

package com.test;

class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Test {

    public static void main(String[] args) {
        // given
        Person person = new Person("ํ™๊ธธ๋™", 26);
        Person copyPerson = person;

        // when
        copyPerson.setName("๊น€์˜๋ฏผ");
        copyPerson.setAge(26);

        // then
        System.out.println(person); // Person{name='๊น€์˜๋ฏผ', age=26}
        System.out.println(copyPerson); // Person{name='๊น€์˜๋ฏผ', age=26}
    }
}

Java ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋‹ค๋ณด๋ฉด ๋ฐฐ์—ด์ด๋‚˜, ์ปฌ๋ ‰์…˜(List, Set..)์„ ๋ณต์‚ฌํ•  ์ผ์ด ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š”๋ฐ,
์–•์€ ๋ณต์‚ฌ, ๊นŠ์€ ๋ณต์‚ฌ์— ๋Œ€ํ•œ ๊ฐœ๋… ์—†์ด ๋งˆ๊ตฌ์žก์ด๋กœ ๋ณต์‚ฌํ•˜์ง€๋ง์ž... ์ด์Šˆ๋กœ ์ด์–ด์งˆ์ˆ˜๋„ ์žˆ๋‹ค.

  • ์–•์€ ๋ณต์‚ฌ๋Š” ์ฃผ์†Œ์— ์˜ํ•œ ์ฐธ์กฐ, call by reference์™€ ์œ ์‚ฌํ•œ ๊ฐœ๋…์„ ๊ฐ–๋Š”๋‹ค
  • ๋ณต์‚ฌํ•˜๋ ค๋Š” ์›๋ณธ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ ์ƒˆ๋กœ์šด ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์›๋ณธ ๊ฐ์ฒด ์ฐธ์กฐ

์œ„ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ํ˜„์žฌ name, age๋ฅผ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Person ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•œ๋‹ค.
main ํ•จ์ˆ˜์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์‹ ๊ทœ Person ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ํ›„์— copyPerson ๋ณ€์ˆ˜์— ์–•์€ ๋ณต์‚ฌ๋ฅผ ํ•˜์˜€๋‹ค.

๊ธฐ๋Œ€ํ•œ ๋ถ€๋ถ„์€ person ๋ณ€์ˆ˜๋Š” 'ํ™๊ธธ๋™', 26 ์ด๋ผ๋Š” ๊ฐ’์ด ๋‚˜์˜ค๊ณ , copyPerson ๋ณ€์ˆ˜๋Š” '๊น€์˜๋ฏผ', '26'์ด ๋‚˜์˜ฌ ๊ฒƒ์ด๋ผ ์˜ˆ์ƒํ•˜์ง€๋งŒ
์‹ค์ œ ๊ฒฐ๊ณผ์—์„œ๋Š” 2๊ฐœ์˜ ๊ฐ์ฒด ๋ชจ๋‘ ์•„๋ž˜์™€ ๊ฐ™์ด '๊น€์˜๋ฏผ', 26์ด๋ผ๋Š” ๊ฐ’์„ ์‘๋‹ตํ•˜๊ฒŒ ๋œ๋‹ค.

// ์ฝ˜์†” ๊ฒฐ๊ณผ
Person{name='๊น€์˜๋ฏผ', age=26}
Person{name='๊น€์˜๋ฏผ', age=26}

Process finished with exit code 0

โ“ ์™œ 2๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ผ๊นŒ?

2๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ ์ด์œ ๋Š” person ๋ณ€์ˆ˜์˜ ๊ฐ์ฒด ์ฐธ์กฐ ๊ฐ’์„ copyPerson ๋ณ€์ˆ˜์— ์–•์€ ๋ณต์‚ฌ ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์•„๋งˆ ์‹ค์ œ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์ƒ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทธ๋ฆผ์œผ๋กœ ์ƒ์„ฑ์ด ๋  ๊ฒƒ ์ด๋‹ค. (๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ๋ฒˆ์ง€ ์ฐธ์กฐ)

๐Ÿค” ์™œ ๊ตณ์ด ์–•์€ ๋ณต์‚ฌ๋ฅผ ํ•ด์•ผ ํ• ๊นŒ? ๊ทธ๋ฆฌ๊ณ  ์–ด๋– ํ•œ ๊ฒฝ์šฐ์— ์ฃผ๋กœ ์‚ฌ์šฉํ• ๊นŒ?

shallow_deep_copy.png

๋งŒ์•ฝ ๊ฐ์ฒด์˜ ์ฃผ์†Œ๊ฐ’ ๋ณต์‚ฌ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ๊ฐ’์„ ๋ณต์‚ฌํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด ๊นŠ์€ ๋ณต์‚ฌ(deep copy)๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.
๋‹ค์Œ์€ ๊นŠ์€ ๋ณต์‚ฌ์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

01-3. ๊นŠ์€ ๋ณต์‚ฌ

๊นŠ์€ ๋ณต์‚ฌ(deep copy)๋ž€ ๊ฐ์ฒด์˜ ์ฃผ์†Œ๊ฐ’์ด ์•„๋‹Œ ์ƒˆ๋กœ์šด ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ๊ฐ’์„ ๋ณต์‚ฌํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋Œ€ํ‘œ์ ์œผ๋กœ 3๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค.

  1. ๋ณต์‚ฌ ์ƒ์„ฑ์ž ๋˜๋Š” ๋ณต์‚ฌ ํŒฉํ† ๋ฆฌ ์ด์šฉํ•˜์—ฌ ๋ณต์‚ฌ
  2. ์ง์ ‘ ๊ฐ์ฒด ์ƒ์„ฑ ํ›„ ๋ณต์‚ฌ
  3. Clonable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ํ•˜์—ฌ clone() ํ•จ์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ›„ ๋ณต์‚ฌ

โœ… ๋ณต์‚ฌ ์ƒ์„ฑ์ž ๋˜๋Š” ๋ณต์‚ฌ ํŒฉํ† ๋ฆฌ ์‚ฌ์šฉ

package com.test;

class CopyObject {
    private String name;
    private int age;

    /* NoArgsConstructor */
    public CopyObject() {
    }

    /* ๋ณต์‚ฌ ์ƒ์„ฑ์ž */
    public CopyObject(CopyObject copyObject) {
        this.name = copyObject.getName();
        this.age = copyObject.getAge();
    }

    /* ๋ณต์‚ฌ ํŒฉํ† ๋ฆฌ */
    public static CopyObject copy(CopyObject copyObject) {
        CopyObject copy = new CopyObject(copyObject.getName(), copyObject.getAge()); // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ํ˜ธ์ถœ
        return copy;
    }

    /* ์ƒ์„ฑ์ž */
    public CopyObject(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public class Test {

    public static void main(String[] args) {
        CopyObject original = new CopyObject("YM", 30); // ์›๋ณธ
        CopyObject copyConstructor = new CopyObject(original); // ์ƒ์„ฑ์ž ๋ณต์‚ฌ
        CopyObject copyFactory = CopyObject.copy(original); // ํŒฉํ† ๋ฆฌ ๋ณต์‚ฌ

        System.out.println("[๋ณ€๊ฒฝ ์ „] original = " + original.getName()); // [๋ณ€๊ฒฝ ์ „] original = YM
        System.out.println("[๋ณ€๊ฒฝ ์ „] copyConstructor = " + copyConstructor.getName()); // [๋ณ€๊ฒฝ ์ „] copyConstructor = YM
        System.out.println("[๋ณ€๊ฒฝ ์ „] copyFactory = " + copyFactory.getName() + "\n"); // [๋ณ€๊ฒฝ ์ „] copyFactory = YM

        copyConstructor.setName("KIM");
        copyFactory.setName("JUNE");

        System.out.println("[๋ณ€๊ฒฝ ํ›„] original = " + original.getName()); // [๋ณ€๊ฒฝ ํ›„] original = YM
        System.out.println("[๋ณ€๊ฒฝ ํ›„] copyConstructor = " + copyConstructor.getName()); // [๋ณ€๊ฒฝ ํ›„] copyConstructor = KIM
        System.out.println("[๋ณ€๊ฒฝ ํ›„] copyFactory = " + copyFactory.getName()); // [๋ณ€๊ฒฝ ํ›„] copyFactory = JUNE
    }
}
// ์ฝ˜์†” ๊ฒฐ๊ณผ
[๋ณ€๊ฒฝ ์ „] original = YM
[๋ณ€๊ฒฝ ์ „] copyConstructor = YM
[๋ณ€๊ฒฝ ์ „] copyFactory = YM

[๋ณ€๊ฒฝ ํ›„] original = YM
[๋ณ€๊ฒฝ ํ›„] copyConstructor = KIM
[๋ณ€๊ฒฝ ํ›„] copyFactory = JUNE
  • ๋ณต์‚ฌ ์ƒ์„ฑ์ž ๊ทธ๋ฆฌ๊ณ  ๋ณต์‚ฌ ํŒฉํ† ๋ฆฌ๋Š” ๊นŠ์€ ๋ณต์‚ฌ

โœ… ์ง์ ‘ ๊ฐ์ฒด ์ƒ์„ฑ ํ›„ ๋ณต์‚ฌ

public class Test {

    public static void main(String[] args) {
        CopyObject c1 = new CopyObject("AAA", 40);
        CopyObject c2 = new CopyObject(c1.getName(), c1.getAge());
        c2.setName("๋ณ€๊ฒฝํ•˜์ง€๋กฑ");
        c2.setAge(3333);
        //System.out.println(c1);
        //System.out.println(c2);
        System.out.println(c1.getName());
        System.out.println(c2.getName());
    }
}
// ์ฝ˜์†” ๊ฒฐ๊ณผ
//com.test.CopyObject@3796751b
//com.test.CopyObject@67b64c45

AAA
๋ณ€๊ฒฝํ•˜์ง€๋กฑ
  • ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๋ฉฐ, ๋ฐ์ดํ„ฐ๋„ ๋‹ค๋ฆ„

โœ… Clonable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ํ•˜์—ฌ clone() ํ•จ์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ›„ ๊นŠ์€ ๋ณต์‚ฌ

// Object.java
// Java Doc... ์ฃผ์„ ์ค‘๋žต
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
// Cloneable.java
// Java Doc... ์ฃผ์„ ์ค‘๋žต
public interface Cloneable {
}

clone์€ Object์— ์ •์˜๋˜์–ด ์žˆ๋‹ค, ์“ฐ๊ณ  ์‹ถ์œผ๋ฉด 'Cloneable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„' ํ›„ ์“ฐ๋ผ๊ณ  ํ•œ๋‹ค? ๐Ÿค”
๊ทผ๋ฐ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์—ด์–ด๋ณด๋ฉด ๋ณธ๋ฌธ์ด ๋น„์–ด์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค(์‹ค์ œ๋กœ๋Š” ๋งˆ์ปค ์ธํ„ฐํŽ˜์ด์Šค)
์ฐธ๊ณ  : Java: Cloneable์— ๋Œ€ํ•œ ๊ณ ์ฐฐ

์‹ค์ œ Object ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ€๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด clone() ๋ฉ”์„œ๋“œ๊ฐ€ protected native ๋กœ ์„ ์–ธ๋˜์–ด ์žˆ๋Š”๊ฑธ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.
clone() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฉฐ, ๋งŒ์•ฝ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด CloneNotSupportedException์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

native ํ‚ค์›Œ๋“œ?

native ํ‚ค์›Œ๋“œ๋Š” ์ž๋ฐ”๊ฐ€ ์•„๋‹Œ ์–ธ์–ด(C, C++)๋กœ ๊ตฌํ˜„ ํ›„ ์ž๋ฐ”์—์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ด์šฉํ•˜๋Š” ํ‚ค์›Œ๋“œ์ด๋‹ค.
์ž๋ฐ”๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šด ๊ฒƒ์„ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๊ตฌํ˜„ ํ›„ ์ž๋ฐ”์—์„œ ์‚ฌ์šฉํ•œ๋‹ค. ๊ตฌํ˜„ํ• ๋•Œ JNI(Java Native Interface)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์‹ค์ œ๋กœ Cloneable์„ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ํŒ๋‹จํ•˜๋Š” ๋ถ€๋ถ„์€ jvm.cpp ์†Œ์Šค ์•ˆ์—์„œ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.

package com.test;

class CloneableObject implements Cloneable {
    private String name; // ์ด๋ฆ„
    private int age; // ๋‚˜์ด

    // Constructor
    public CloneableObject(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // Object ํด๋ž˜์Šค์˜ clone ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ
    @Override
    public CloneableObject clone() {
        try {
            return (CloneableObject) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

public class Clone {

    public static void main(String[] args) {
        // ์‹ ๊ทœ ๊ฐ์ฒด ์ƒ์„ฑ
        CloneableObject cloneableObject1 = new CloneableObject("KKK", 13);
        
        // ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๊นŠ์€ ๋ณต์‚ฌ(Deep Copy ์ˆ˜ํ–‰)
        CloneableObject cloneableObject2 = cloneableObject1.clone();

        // ๊ฒฐ๊ณผ ์ถœ๋ ฅ
        System.out.println(cloneableObject1);
        System.out.println(cloneableObject2);
        System.out.println(cloneableObject1.hashCode());
        System.out.println(cloneableObject2.hashCode());
        System.out.println(cloneableObject1.getName());
        System.out.println(cloneableObject2.getName());
    }
}

๋ณต์‚ฌ๋ฅผ ํ•˜๊ณ ์ž ํ•˜๋Š” Obj(CloneableObject)์—์„œ Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  Object.clone() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•œ๋‹ค.
ํ›„์— ํ•ด๋‹น ๊ฐ์ฒด์˜ clone() ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ์ด ๋œ๋‹ค.

// ์ถœ๋ ฅ ๊ฒฐ๊ณผ
cloneableObject1 => com.test.CloneableObject@7e0ea639
cloneableObject2 => com.test.CloneableObject@3d24753a
cloneableObject1.hashCode() => 2114889273
cloneableObject2.hashCode() => 1025799482
cloneableObject1.getName => KKK
cloneableObject2.getName() => KKK

99. ์ฐธ๊ณ  ์ž๋ฃŒ