반응형

얕은 복사 (Shallow Copy) 란?

public class Main {

    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "Tom";
        Student s2 = s1;

        s2.name = "Harry";
        System.out.println("s1의 이름 : " + s1.name);    // Harry 출력
    }
}

class Student {
    String name;
}
  • 위의 코드에서 Student s1 생성 후 이름을 "Tom"이라고 정했음
  • Student s2에는 s1을 그대로 넣어줬고, s2의 이름을 "Harry"로 변경
  • 그리고 s1의 이름을 출력해보니 "Harry"가 출력됨
  • s2의 이름을 변경했는데 왜 s1의 이름까지 바뀐것일까? 이는 s2는 s1을 "Shallow Copy"했기 때문
  • https://chb2005.tistory.com/5 여기서 정리한 내용 중에 참조형 타입은 4byte로 메모리 주소를 가르킨다고 했었음
  • 이 때문에 s2 = s1을 해주면 s1의 값들이 s2로 복사되는 것이 아닌 Heap에 올라간 "Tom"이라는 학생명 정보를 가진 객체의 메모리주소가 복사됨
  • 따라서 s2 = s1을 해주면 s2는 s1과 같은 주소값을 가르키게 되는 것이고 s2.name을 변경하면 s1, s2가 가리키는 객체의 name이 변경되기 때문에 s1.name을 출력해도 변경됨

깊은 복사 (Deep Copy) 란?

  • 깊은 복사란 얕은 복사와 달리 주소값 복사가 아닌 실제 값들을 복사해 넣어주는 것을 의미

깊은 복사 구현 방법 3가지

직접 객체 생성 후 변수별로 각각 복사

public class Main {

    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "Tom";

        Student s2 = new Student();
        s2.name = s1.name;        // 직접 복사

        s2.name = "Harry";        // 값 변경
        System.out.println("s1의 이름 : " + s1.name);    // Tom 출력
        System.out.println("s2의 이름 : " + s2.name);    // Harry 출력
    }
}

class Student{
    String name;
}

생성자 활용

public class Main {

    public static void main(String[] args) {
        Student s1 = new Student("Tom");
        Student s2 = new Student(s1);

        s2.name = "Harry";
        System.out.println("s1의 이름 : " + s1.name);      // Tom 출력
        System.out.println("s2의 이름 : " + s2.name);      // Harry 출력
    }
}

class Student{
    String name;

    Student(String name) {
        this.name = name;
    }

    Student(Student s) {
        this.name = s.name;
    }
}

Cloneable구현을 통한 clone 메소드 재정의

public class Main {

    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1 = new Student();
        s1.name = "Tom";

        Student s2 = s1.clone();
        s2.name = "Harry";
        System.out.println("s1의 이름 : " + s1.name);        // Tom 출력
        System.out.println("s2의 이름 : " + s2.name);        // Harry 출력
    }
}

class Student implements Cloneable{
    String name;

    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
}
반응형

↓ 클릭시 이동

복사했습니다!