카테고리 없음 / / 2023. 7. 19. 23:55

2023 하계 모각코 4차 종료

7/19

item 13 14

21:00 ~ 24:00

Object.clone()과 Cloneable의 동작 방식

먼저 이 메서드의 동작 방식에 대해 알아보자. 일반적인 경우와 달리 이 메서드는 선언은 Object 클래스에 되어있지만 빈 인터페이스인 Cloneable을 구현해야만 제대로 작동하도록 설계되어 있다.

CloneNotSupportedException – if the object's class does not support the Cloneable interface. Subclasses that override the clone method can also throw this exception to indicate that an instance cannot be cloned.

Object.clone() API 문서, Cloneable을 구현하지 않은 클래스가 clone()을 호출하면 CloneNotSupportedException이 터진다.

// 메서드가 없는 빈 인터페이스인 Cloneable
public interface Cloneable {
}

또한, Object.clone()은 protected로 선언되어 하위 클래스에서 재정의해주지 않으면 클라이언트에서 호출할 수 없게 되어있다. 이러한 방식은 상위 클래스에서 정의한 clone()을 동작을 인터페이스가 변경하게 되므로 상당히 이례적인 설계라고 할 수 있지만 실무에서 Cloneable을 구현한 클래스가 흔하게 사용되므로 사용법에 대해서는 알아두는게 좋다고 말한다.

올바른 clone() 구현 방법

가변 객체를 참조하지 않는 객체

먼저 모든 필드가 기본 타입이거나 불변 객체를 참조하는 객체 의 경우 어떻게 clone()을 구현해야 되는지 살펴보자.

이런 경우 먼저 super.clone()을 호출한다. 그럼 그렇게 만들어진 객체가 원본과 똑같은 값을 같는 복제본이 된다. 모든 필드가 기본 타입이거나 불변 객체이므로 이렇게 만들어진 복제본에서 더 이상 수정할 것이 없다. 따라서 그대로 반환해도 된다.

public class Number implements Cloneable {
    private final int value; // 기본 타입

    // 생성자 생략

    @Override
    public Number clone() {
        try {
            return (Number) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 도달 불가능
        }
    }
}

여기서 봐야할 것은 먼저 Object.clone()은 Object를 반환하지만 자바에서는 재정의 시 기존 반환 타입의 하위 타입 반환이 가능하므로 Number를 반환하도록 할 수 있다. 이렇게하면 클라이언트에서 일일이 형변환을 해줄 필요가 없어진다. 또한, Number 클래스가 Cloneable을 구현하고 다른 클래스를 상속받지 않으니 CloneNotSupportedException이 터질 일이 없으므로 불필요한 checked exception을 try-catch로 감싸서 메서드의 throws 절을 없애고 클라이언트에서 더 편하게 사용할 수 있도록 해주면 좋다고 한다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유