개발 등/중급

Object 클래스 : clone()

darkhorizon 2008. 9. 3. 10:38
728x90
반응형
자바에서 인스턴스를 참조할 때는 대부분 주소값을 복사하는 차원에서 이루어졌다.

    Test t1 = new Test();
    Test t2 = t1;
따라서 t1.hashCode() == t2.hashCode(); 의 결과는 True 가 된다.
하지만 주소값의 복사가 아닌 메모리 차원에서 복사를 하려면 어떻게 해야 할 것인가?
그럴 때 필요한 것이 바로 clone 메서드이다.
clone 메서드는 Object 클래스에 정의되어 있는 메서드이다.

 protected native Object clone();
    Creates and returns a copy of this object. 

즉 API에서 정의된 대로 해당 객체를 생성한 후 리턴하는 역할을 한다.
만일 clone() 을 오버라이딩 하겠다면 반드시 super.clone(); 으로 호출해야 한다.
아니면 오버라이딩 된 자신의 메서드를 호출하는 결과가 나오기 때문이다.

public Object clone(){
    Object oldObj=null;
    oldObj=clone();   // 에러 발생!
    oldObj=super.clone();
    return oldObj;   // 리턴 타입이 Object이기 때문에 이 메서들를 호출할 때는 다운캐스팅을 해야 한다.
}

하지만 clone()를 단순히 재정의 할 뿐 오버라이딩 하는 것이 아니라면 굳이 super를 쓰지 않아도 된다.

public Object realCopy(){
    Object newObj=null;
    newObj=clone();
    return newObj;
}

문제는 단순히 Object 클래스의 clone()를 호출하는 것만으로는 완전하지 않다는 것이다.
clone()를 완전하게 구현하기 위해서는 Cloneable 이라는 인터페이스도 함꼐 구현해야만 한다.
인터페이스를 구현하려면 인터페이스에 정의된 추상메서드까지 구현해야 하는 게 아닌가라는 걱정은 안해도 된다. API에 있는 Cloneable 인터페이스를 보면 이해가 갈 것이다.

    public interface Cloneable {}

이게 전부다.
즉 클래스 이름 곁에 implements Cloneabe 만 덧붙여 주면 끝이다.
만일 이 인터페이스를 구현하지 않으면 CloneNotSupportedException 이 발생하게 된다.

class Test implements Cloneable{
    private String name;
   
    public Test(){
       this("Original Test");
    }
    public Test(String name){
       this.name=name;
    }
    public Object copy(){
       Object obj=null;
       try{
          obj=clone();
        }catch(CloneNotSupportedException ce){
            System.out.println("객체를 생성할 수 없습니다");
        }
       return obj;
    }
    public String toString(){
       return this.name+" "+this.hashCode();
    }
}

public class TestMain{
    public static void main(String[] args){
       Test t1 = new Test("원본");
       Test t2=(Test) t1.copy();

       System.out.println(t1);
       System.out.println(t2);
    }
}
728x90