article thumbnail image
Published 2023. 8. 10. 21:46
반응형

🧐 Cloneable 정의


  • 단순히 복사를 위한 marker interface이다.
    marker interface는 아무것도 존재하지 않는 interface를 의미한다.
  • interface를 구현하고, super.clone()을 호출하면 사용할 수 있다.
    만약 interface를 구현하지 않는 클래스가 호출하게 되면 CloneNotSupportedException가 발생한다,.
  • 피상 복사(Shallow Copy)이다.
  • clone() 메서드의 기본 제공은 Object 클래스가 제공한다.
  • java.lang 패키지에 위치하므로, Import가 필요없다.

🧐 주의 사항


  1. 피상 복사(Shallow Copy)이다.

피상 복사를 필드 대 필드 복사라고 하는데 이는 필드를 주소만 참조하는 것을 의미하고, Deep Copy하지 않는 것을 의미한다.

즉, 필드는 피상 복사가 되고, Cloneable 구현체는 새로운 메모리에 복사를 하게 된다.

만약 Deep Copy를 하기 위해서는 필드까지 직접 Copy 코드를 구현해줘야 한다.

@Test
void cloneable_shallow_copy() throws CloneNotSupportedException {
  // given
  List<String> strings = Arrays.asList("1", "2");
  CloneDugi sut = new CloneDugi(strings);

  // when
  CloneDugi clone = sut.clone();

  // then
  assertThat(clone).isNotSameAs(sut);
  assertThat(clone.getStrs()).isSameAs(sut.getStrs());

  strings.set(0, "3");
  assertThat(sut.getStrs().get(0)).isEqualTo("3");
  assertThat(clone.getStrs().get(0)).isEqualTo("3");
}

위 코드를 보면 구현체는 CloneDugi 클래스는 메모리 주소가 다른 것을 알 수 있고, 필드 주소를 동일한 것을 확인할 수 있다.

  1. Cloneable이 아닌 Object에 존재하고, protected이기 때문에 외부에서 호출이 불가능하다.
@Test
void protect라니() throws CloneNotSupportedException {
  Object clone = new Dugi("dd").clone();    // protectd라서 에러
    Object clone = new Dugi("dd").toString(); // public이라서 가능
}

class Dugi implements Cloneable {

  private final String name;

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

    // 해결하기 위해 override 필요
    @Override
    protected Object clone() throws CloneNotSupportedException {
      return super.clone();
    }
}

근데 사실상 이게 그렇게 단점이라고 하기는 어려운 것 같다.

그냥 override하면 끝이기 때문이다.

  1. 구현하기 않은 클래스가 Object.clone()을 하면 CloneNotSupportedException이 발상한다.
반응형
복사했습니다!