Dipa's document :: [JAVA] Object클레스 - clone()

Object클레스의 clone()메소드는 복제를 의미한다. 따로 설명을 하기가 어려운데..그냥 정말 복제다.

복제를 하는 이유는 무엇일까? 원본 객체를 유지를 하기위한 방패막이라고나 할까?ㅋㅋㅋ

하지만 복재는 두가지 분류로 나뉜다. 얕은복제, 깊은복제

1) 얕은 복제 : 객체의 기본 타입만 복제(참조 타입의경우 객체의 번지가 복사 -> 참조를 바꾸면? 같이 바뀐다..)

2) 깊은 복제 : 객체의 기본 타입, 참조 타입 모두가 바뀐다.

그럼, 이제 코드를 한번 확인을 해보자.

package object;

public class Member implements Cloneable{
	public String id;
	public String name;
	public String password;
	public int age;
	public boolean adult;
	
	public Member(String id, String name, String password, int age, boolean adult){
		this.id = id;
		this.name = name;
		this.password = password;
		this.age = age;
		this.adult = adult;
	}
	
	public Member getMember(){
		Member cloned = null;
		try {
			cloned = (Member)this.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloned;
	}
}

Clone()메소드를 작성시에 유의사항은 복사할 객체를 Cloneable 인터페이스를 구현을 해야하고, Clone()메소드에 대한 예외 처리를 해야 한다는 것이다.

getMember()드에서 object클레스의 clone()을 override를 해야하지만 default로는 얕은복제를 하기떄문에 얕은 복제를 먼저 구현을 하고 실험을 해보자.


package object;

public class MemberExample {
	public static void main(String[] args){
		Member original = new Member("blue","홍길동","12345",25,true);
		
		Member cloned = original.getMember();
		original.age = 30;
		
		System.out.println("[원본 객체의 필드값]");
		System.out.println("id: " + original.id);
		System.out.println("name: " + original.name);
		System.out.println("password: " + original.password);
		System.out.println("age: " + original.age);
		System.out.println("adult: " + original.adult);
		
		System.out.println();
		
		System.out.println("[복제 객체의 필드값]");
		System.out.println("id: " + cloned.id);
		System.out.println("name: " + cloned.name);
		System.out.println("password: " + cloned.password);
		System.out.println("age: " + cloned.age);
		System.out.println("adult: " + cloned.adult);
	}
}

결과에서 나왔듯이 원본객체를 바꿔도 복제한 객체에는 바뀌지 않는것을 볼수가 있다.

그런데 여기서 의문을 가지는 개발자가 있을것이다. 처음에는 얕은 복제는 기본타입만 복제가 된다고 했는데 String을 바꿨는데 원본과 복제된 객체의 값이 다르다? 그러면 참조타입도 복제가 되었다는 말아닌가???? ㅡㅡ 여기서.. 여기서 나의대답은!! String은 참조 타입이다. 하지만 String같은경우는 값이 바뀌는 것이 아니라 오히려 그 데이터의 객체를 하나 생성을 한다...

말이 어려울수 있으니..이부분에 대해서는 String 클레스에서 다시한번 설명하도록 하겠다.


package object;

import java.util.Arrays;

public class Member2 implements Cloneable{
	public String name;
	public int age;
	public int[] scores;
	public Car car;
	
	public Member2(String name, int age, int[] scores, Car car) {
		this.name = name;
		this.age = age;
		this.scores = scores;
		this.car = car;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Member2 cloned = (Member2)super.clone();
		cloned.scores = Arrays.copyOf(this.scores, this.scores.length);
		cloned.car = new Car(this.car.model);
		
		return cloned;
	}
	
	public Member2 getMember(){
		Member2 cloned = null;
		try {
			cloned = (Member2)this.clone();
		} catch (CloneNotSupportedException e) {}
		
		return cloned;
	}
}

깊은 복제를 하기위해서는 override를 해야하는데, 일단 기본타입을 위해서 먼저 object클레스의 clone()을 한번 호출을한뒤, 남은 클레스타입과 배열타입을 복사를 한다.

package object;

public class Member2Example {
	public static void main(String[] args){
		Member2 original = new Member2("홍길동",25,new int[]{90,90},new Car("소나타"));
		
		Member2 cloned = original.getMember();
		cloned.scores[0] = 50;
		cloned.scores[1] = 50;
		
		System.out.println("[원본 객체의 필드값]");
		System.out.println("name : " + original.name );
		System.out.println("age : " + original.age );
		for(int i =0;i<original.scores.length;i++){
			System.out.print(original.scores[i] + " ");
		}
		
		System.out.println();
		
		System.out.println("[복제 객체의 필드값]");
		System.out.println("name : " + cloned.name );
		System.out.println("age : " + cloned.age );
		for(int i =0;i<cloned.scores.length;i++){
			System.out.print(cloned.scores[i] + " ");
		}
	}
}


Posted by SH후니
,