본문 바로가기

Java

[Java] Clone

복사 대상이 되는 클래스는 java.lang.Cloneable 인터페이스를 반드시 구현(implements)해야 한다.

 

복사 대상이 되는 클래스가 직접 구현해도 상관없고, 상위 클래스 어딘가에서 구현해도 괜찮으며, Cloneable의 하위 인터페이스를 구현해도 상관없다.

 

Cloneable 인터페이스를 구현한 클래스의 인스턴스는 clone메소드를 호출하면 복사된다.

 

clone메소드를 사용하는 방법은

 

n         public Object clone()메서드의 재정의와 protected native Object clone메서드 사용

 

인데..

 

 

아래의 경우 super를 붙여준 이유는 super를 빼버리면 자기 자신이 가지고 있는

 

(즉, 오버라이드한 clone)을 호출하게 되므로 무한루프가 돌아서 stack over flow가 발생하게 된다.

 

따라서 아래와 같이 해주던지..super를 빼려고 한다면

 

createclone등으로 이름을 바꿔주고 호출하면 된다...

 

 

 

class SimpleClone implements Cloneable{       

             public int count=0;

             public SimpleClone(int count){

                           this.count = count;

             }           

             public Object clone(){                      

                           Object o = null;                  

                           try{                     

                                        o = super.clone();              

                           }catch (Exception e){System.out.println("can't clone object");}

                           return o; 

             }

}

public class LCopy{

             public static void main(String args[]){

                           SimpleClone sc1 = new SimpleClone(22);

                           SimpleClone sc2 = (SimpleClone)sc1.clone();

                           System.out.println("sc1 hashCode:"+sc1.hashCode() + ", count의값:" + sc1.count);

                           System.out.println("sc2 hashCode:"+sc2.hashCode() + ", count의값:" + sc2.count);

             }

}

 

%헷갈리지 말자%

보통 서적에 나와있는 clone을 사용하려면 그 클래스는 cloneable을 구현하고

clone메소드를 재정의 해줘야 한다고 나온다.

 

여기서 생각해보면 clone()메소드는 java.lang.Object의 메소드이고 Object 클래스는 모든 클래스의 상위 클래스인데 왜 굳이 clone()메소드를 오버라이드 해줘야 한다고 할까..?

 

즉, public TestClone implements Clonable{...}

라는 클래스가 있을때 그냥 clone이라고 사용을 해도 될텐데 왜 재정의가 필요하다고 할까?

 

clone이라는 것은 자기 자신을 복제하는 메소드이다. 보통 다른 클래스에서

 

복제를 요청하거나 위의 경우만해도 Main클래스에서 테스트를 위해 clone을 호출하고 있는데

 

이 clone메소드는 Protected형이다. 따라서 재정의가 없으면 이 메소드를 다른 패키지나 상속관계에 있지 않는 클래스들은 호출 할 수 없다는 것이다.

 

따라서..clone()메소드를

 

public Object clone(){

   return super.clone();

}

 

로 재정의 해주던가 아니면 아예 다른 이름으로

 

public Object runClone(){

  return clone(); //이 경우에는 super를 안 붙여도 됀다. 같은 이름의 메소드로 재정의 하지 않았기 때문에 자동적으로 상위 클래스에 있는 clone()메소드가 호출된다.

}

 

그래서 재정의를 해줘야 한다는 말이 나오는 것이다.

 

같은 이름으로 오버라이드를 해주던 다른 이름으로 다른 클래스에서 접근가능한 클래스를

만들어주던간에 어쨋든 구현을 해주어야 다른 클래스에서 접근이 가능하기 때문이다.

 

 

혹시 인터페이스를 구현했기 때문에 거기에

 

있는 추상메소드를 구현해야 한다고 생각하지 말자. Cloneable 인터페이스는 아무런 추상메소드도

 

가지고 있지 않다. 단지 이 인터페이스를 implements한 클래스는 clone을 사용하여 복사 가능하다

 

..라고 나타내 주는 것에 불과하다.