멘토링

Deep, Shallow and Lazy Copy

langsamUndStetig 2022. 6. 17. 18:39

Shallow copy (얕은 복사)

 

 얕은 복사는 참조값을 다른 새로운 변수에 넣어줌으로써 간단하게 실험해볼 수 있다. 

이렇게 할 경우, 객체의 주소를 참조한 다른 변수에서 실제 객체의 값을 변경해버릴 수 있다.

public class Main {
  public static void main(String[] args) {
    int[] arr = {2, 3, 5};
    int[] var = arr;
    System.out.println(arr[0]); // 2
    var[0] = 4; // var의 인덱스 0번 값 변경
    System.out.println(arr[0]); // 출력값 4, 즉 arr의 값에 영향을 주었음
    System.out.println(arr.equals(var)); // true
    System.out.println(arr.hashCode());  // arr과 var은 hashCode()마저 동일함
    System.out.println(var.hashCode());
  }
}

 

깊은 복사

깊은 복사는 같은 값을 가진 동일한 객체를 하나 더 생성해서, 변수에 참조값을 할당하는 것이다. 

즉, 하나의 객체를 다루는 얕은 복사와 달리, 개별적인 객체를 다루는 것을 말한다.

package basic;


import java.util.Arrays;

public class Main {
  private int[] data;

  public Main(int[] values) {
    data = new int[values.length];
    for (int i = 0; i < values.length; i++) {
      data[i] = values[i];
    }
  }
  public void showData() {
    System.out.println(Arrays.toString(data));
  }

  public static void main(String[] args) {
    int[] vals = {3, 5, 6};
    Main m = new Main(vals); // {3, 5, 6}
    System.out.println(vals.hashCode()); // 2003749087
    System.out.println(m.hashCode()); // 1324119927
    System.out.println(vals); // [I@776ec8df
    System.out.println(m); //basic.Main@4eec7777
    m.showData();  // {3, 5, 6}
    vals[0] = 2; // {2, 5, 6}
    m.showData(); // {3, 5, 6}
    System.out.println(Arrays.toString(vals));
    System.out.println(vals.hashCode());
    System.out.println(m.hashCode());
  }
}


 

Lazy Copy

 

 이 방법은 얕은 복사와 깊은 복사가 혼합한 형태라고 한다. 이것의 작동방식은 먼저 빠른 얕은 복사를 사용하는 것이다. 그리고 counter를 이용해서 한 데이터를 얼마나 많은 객체들이  공유하는지 추적한다. 그래서 한 객체를 변경할 때, counter를 검사하여, 데이터 공유를 확인하고 필요시 깊은 복사를 할 수  있다.

Lazy copy는 깊은 복사처럼 보이지만, 가능한 경우엔 얕은 복사를 사용해서 속도의 이점이 있다. 단점은 다소 높지만 일정한 카운터에 의해 발생하는 기본 코스트다. 또한 특정 상황에선 순환참조가 문제를 일으킬 수 있다고 한다.

 

 

public class Main {
  public static void main(String[] args) {
    int a = 2; // 기본타입에서 얕은 복사는 깊은 복사처럼 작동한다.
    int b = a;
    b = 3;
    System.out.println(a);
    System.out.println(b);

    String c = "Ho"; // String 타입도 마찬가지로 깊은 복사처럼 작동한다.
    String d = c;
    d = "Hello";
    System.out.println(c);
    System.out.println(d);
    String h = new String("Ho");
    String e = h;
    e = new String("Hello");
    System.out.println(h);
    System.out.println(e);
  }

}

 

참고 자료

 

https://www.geeksforgeeks.org/deep-shallow-lazy-copy-java-examples/