[JAVA] 깊은복사 vs 얕은복사

eunniverse·2024년 3월 3일
0
post-custom-banner
  • 확인하게 된 계기

    • 비밀번호가 변경되지 않는다는 이슈로 디버깅 하던 와중 개념이 궁금해졌다.
  • 깊은복사 vs 얕은복사

    • 깊은복사 : ‘실제 값’ 을 새로운 메모리 공간에 복사
    • 얕은 복사 : ‘주소 값’ 을 복사
  • 얕은복사

    • call-by-reference 와 유사한 개념이다.

    • 복사 객체가 원본 객체에 종속적이다.

    • 원본 객체가 수정되는 경우 복사 객체가 원본 객체와 동일하게 변동이 생긴다.

    • 예시

      import lombok.AllArgsConstructor;
      import lombok.Getter;
      import lombok.NoArgsConstructor;
      import lombok.Setter;
      import org.junit.Test;
      
      public class CopyTest {
          @Test
          public void shallowCopy() {
              CopyObject obj = new CopyObject(30, "euni");
              CopyObject obj2 = obj;
      
              System.out.println("obj value : " + obj.getName() + " -> " + obj.getIdx());
              System.out.println("obj2 value : " + obj2.getName() + " -> " + obj2.getIdx());
      
              obj2.setIdx(40);
              obj2.setName("euni2");
              System.out.println("obj value : " + obj.getName() + " -> " + obj.getIdx());
              System.out.println("obj2 value : " + obj2.getName() + " -> " + obj2.getIdx());
          }
      }
      
      @Getter
      @Setter
      @NoArgsConstructor
      @AllArgsConstructor
      class CopyObject {
          private int idx;
          private String name;
      }
    • 결과는??

      • obj2 = obj 로 주소값을 변경했기 때문에 참조하고 있는 값이 같다.
      • 복사한 객체 변경 → 기존 객체도 변경됨!
    • 메모리 구조 (블로그 참조)

      stack 영역에 기존 object 와 복사한 object 가 있고, heap 영역에서 두 개의 object 가 참조하는 데이터는 같다.

      → 따라서 두 개의 object 주소는 같다.

  • 깊은 복사

    • 기존 인스턴스 값 모두를 복사하여 원본 객체로부터 독립적인 객체를 생성한다.
    • call-by-values 와 유사한 개념이다.
    • 모든 인스턴스 값을 갖고 오기 때문에 얕은 복사에 비해 상대적으로 느리고 복잡하다.
    • 구현 방법
      • Cloneable 인터페이스 구현 (블로그 참조)

        public class CopyObject implements Cloneable {
        
            private String name;
            private int age;
        
            public CopyObject() {
            }
        
            public CopyObject(String name, int age) {
                this.name = name;
                this.age = age;
            }
        
            **@Override
            protected CopyObject clone() throws CloneNotSupportedException {
                return (CopyObject) super.clone();
            }**
        
            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 CopyObject {
        
            private String name;
            private int age;
        
            public CopyObject() {
            }
        
            public CopyObject(CopyObject original) {
                this.name = original.name;
                this.age = original.age;
            }
        
            /* 복사 팩터리 */
            **public static CopyObject copy(CopyObject original) {
                CopyObject copy = new CopyObject();
                copy.name = original.name;
                copy.age = original.age;
                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;
            }
        }
        
            @Test
            void shallowCopy() {
                CopyObject original = new CopyObject("JuHyun", 20);
                CopyObject copyConstructor = new CopyObject(original);
                **CopyObject copyFactory = CopyObject.copy(original);**
        
                copyConstructor.setName("JuBal");
                copyFactory.setName("BalJu");
        
                System.out.println(original.getName());
                System.out.println(copyConstructor.getName());
                System.out.println(copyFactory.getName());
            }
    • 메모리 구조 (블로그 참조)
profile
능력이 없는 것을 두려워 말고, 끈기 없는 것을 두려워하라
post-custom-banner

0개의 댓글