jeus1998 / EffectiveJavaGroupStudy

이펙티브 자바 3판 그룹 스터디
1 stars 2 forks source link

03장 아이템13 clone 재정의는 주의해서 진행하라 #16

Open jeus1998 opened 2 weeks ago

jeus1998 commented 1 week ago

이번에 올리신 clone 관련 내용에 오류가 있어서 올려봅니다 @hegunhee

여기서보면 Clonnable 인터페이스는 Object.clone()메서드를 위임할 뿐 무언가 일을 하지는 않습니다.

-> 정확히는 위임이 아닌 Cloneable 인터페이스는 마커 인터페이스로서 JVM이나 컴파일러에게 해당 인터페이스를 구현한 클래스는 Object clone API를 사용이 가능하다 marker(표시) 한다고 볼 수 있겠습니다. 제가 생각하는 위임이란 표현은 대신하다의 의미가 강해서 그렇습니다.

그리고 위의 문단을 보면 일반적으로 field-for-field copy로 복사를 한다고 합니다. 즉 깊은 복사를 통해 필드들이 복사됩니다.

-> Object의 clone API는 깊은 복사가 아니라 얕은 복사(shallow copy)를 합니다. 해당 클래스가 래퍼런스(참조) 타입을 가지면 clone한 객체가 해당 객체를 공유하기 때문에 복제된 객체의 필드 변경이 원본 객체에도 영향을 미치게 됩니다.

@Getter @Setter
public class B {
    private String value;
    public B(String value) {
        this.value = value;
    }
}

@Getter
public class A implements Cloneable{
    private B b;
    public A(B b) {
        this.b = b;
    }
    @Override
    protected Object clone(){
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException e){
            throw new IllegalArgumentException(e);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        A a = new A(new B("A"));
        System.out.println(a.getB().getValue()); // A
        A clone = (A) a.clone(); // Shallow Copy
        System.out.println(a == clone);
        clone.getB().setValue("B");

        System.out.println(a.getB().getValue()); // A -> B 바뀐다.
    }
}
hegunhee commented 1 week ago
  1. 객체단위의 clone()을 구현하게 강제해서 위임이라는 표현을 사용했습니다.

  2. 깊은 복사와 얕은복사의 의미가 계속 반대로 생각하게 되네요 얕은 복사가 값만 복사해서 새로운 객체를 만드는것이고 깊은 복사는 메모리를 공유하게되어서 변경이 일어났을때 복사한곳까지 변경이 전파되는 복사인데 이번에도 잘못 사용했네요 감사합니다 수정해 놓겠습니다.

jeus1998 commented 1 week ago

얕은 복사가 참조 값만 복사해서 객체를 생성하기 때문에 동일한 메모리를 공유하게 되어서 복사한 객체에서 필드 변경이 일어나면 복사한 곳까지 변경이 전파되는 거고 깊은 복사는 참조값을 복사하는 게 아니라 참조 객체를 새로 생성하기 때문에 전파가 일어나지 않습니다.

저두 이 부분 처음에 헷갈렸어요 ㅋㅋ