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);
}
}
즉
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