깊은 복사와 얕은 복사, 왜 알아야 할까?

이건회·2022년 10월 18일
0

자바

목록 보기
3/8
post-custom-banner

공부한 이유

코드를 짤 때 어떤 객체값을 유지한 채로 값을 복사해 새 객체를 만들어 코드를 짤 일이 가끔 생기곤 한다. 그런데 이 때 원본 객체의 값까지도 변경되는 일이 일어나 골머리를 앓곤 했다. 따라서 깊은 복사와 얕은 복사의 차이를 블로그에 기록하여 정확히 짚고 넘어가고자 한다.

얕은 복사(Shallow Copy)란?

얕은 복사는 원본 객체의 "주소 값"만을 복사한다. 간단히 말해 얕은 복사는 복사 대상인 원본 객체와 이름만 다를 뿐, 완전히 같은 주소 공간을 참조하는 같은 객체라고 볼 수 있다. 즉 얕은 복사한 객체의 상태값이 변경되면 원본 객체도 변경되고, 원본 객체의 상태가 변경되면 복사 객체도 변경된다.

깊은 복사(Deep Copy) 란?

깊은 복사는 원본 객체의 "실제 값", 즉 상태값만을 복사한다. 고로 깊은 복사한 객체와 원본 객체의 주소 값은 완전히 다르다. 새로운 주소 공간을 갖는 객체가 생성되는 것이다. 따라서 깊은 복사한 객체의 상태값이 변경된다고 해서, 원본 객체에는 아무런 영향을 끼치지 않는다. 반대도 마찬가지다.

얕은복사 실습

public class ShallowCopy {
  String name;
  int age;

  public ShallowCopy(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;
  }
}

다음과 같은 클래스가 있다고 가정해보자.

class Main {
  public static void main(String[] args) {
    ShallowCopy original = new ShallowCopy("lee",26);
    ShallowCopy copyobject = original; //얕은복사 객체

    copyobject.setAge(20);

    System.out.println("originalAge :"+original.getAge());
    System.out.println("copyobjectAge :"+copyobject.getAge());
  }
}
  • 다음과 같이 original 객체의 age값을 26으로 세팅해 생성한 후, 객체를 copyobject에 얕은 복사한다.

  • copyobject의 age 상태값을 20으로 변경한다.

  • 두 객체를 출력해보겠다.

  • 다음과 같이 original의 age값도 20으로 변경되었다. 두 객체는 얕은 복사 관계이므로 같은 주소 공간을 바라보기 때문임을 꼭 잊지 말자

깊은복사 실습

public class DeepCopy {
  String name;
  int age;

  public DeepCopy(){
  }

  public DeepCopy(DeepCopy original) {
    this.name = new String(original.name);
    this.age = original.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;
  }
}
  • 그렇다면 완전히 새로운 객체를 생성하는 깊은 복사는 어떻게 할 수 있을까?
  • 여러 가지 방법이 있지만 가장 쉬운 방법은 "복사 생성자"를 사용하는 것이다.
  • 8번째 줄에 보면 기존 DeepCopy 객체를 가져와 값을 하나하나 복사해 넣고 새로운 객체를 만드는 생성자가 있다
  • 주의할 점은 int, float, double과 같은 기초 변수 이외의 모든 참조변수(String 등)는 new로 객체를 생성하면서 값을 복사해야 한다. List와 같은 컬렉션의 경우는 for 문으로 순회하면서 값을 복사해야 한다.
class Main {
  public static void main(String[] args) {

    DeepCopy original = new DeepCopy();
    original.setName("lee");
    original.setAge(26);

    DeepCopy copyobject = new DeepCopy(original);
    copyobject.setAge(20);
    
    System.out.println("originalAge :"+original.getAge());
    System.out.println("copyobjectAge :"+copyobject.getAge());
  }
}
  • 이제 original 객체를 DeepCopy 한 후, 복사 객체의 age값을 20으로 변경하여 출력해보겠다

  • 원본 객체의 age값은 유지되는 것을 확인할 수 있다.
  • 두 객체는 깊은 복사 관계이고, 주소 공간을 공유하지 않는 완전히 다른 객체임을 잊지 말자!

즉 근본적으로 얕은 복사는 같은 객체, 깊은 복사는 다른 객체이다!

참고

https://zzang9ha.tistory.com/m/372
https://taeinsoft.com/java/java-deep-shallow-copy/
https://jackjeong.tistory.com/m/100

profile
하마드
post-custom-banner

0개의 댓글