실제 값을 새로운 메모리 공간에 복사하는 것을 의미하며, 얕은 복사(Shallow Copy)는 주소 값을 복사한다는 의미이다.public class Main {
public static void main(String[] args) {
Person person = new Person("person", 26);
Person copyPerson = person;
System.out.println(person.getName());
System.out.println(copyPerson.getName());
copyPerson.setName("copyPerson");
System.out.println(person.getName());
System.out.println(copyPerson.getName());
}
}
person
person
copyPerson
copyPerson

public class Main {
public static void main(String[] args) {
Person person = new Person("person", 26);
Person copyPerson = person;
System.out.println(person.);
System.out.println(copyPerson);
}
}
p0000.Person@43a25848
p0000.Person@43a25848
얕은 복사를 했기 때문에 같은 주소 값이 출력된다.

Clonable 인터페이스는 아무 것도 없는 인터페이스 이지만, 주석을 보면 반드시 Object 클래스의 clone() 메서드를 구현하라고 써져있다.

Object 클래스의 clone() 메서드
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("person", 26);
Person copyPerson = (Person) person.clone();
System.out.println(person);
System.out.println(copyPerson);
System.out.println();
System.out.println(person.getName());
System.out.println(copyPerson.getName());
System.out.println(person.getAge());
System.out.println(copyPerson.getAge());
}
}
class Person implements Cloneable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
p0000.Person@2133c8f8
p0000.Person@43a25848
person
person
26
26
Person 클래스가 Clonable 을 implements 한 후 clone() 메서드를 사용해 복사할 경우 객체의 value 는 같지만 주소가 다른 또 하나의 객체가 만들어지는 모습이다.
Effective Java 13장에서는 clone 재정의는 주의해서 진행하라 라는 부분이 있다.
Cloneable 인터페이스는 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스지만,
아쉽게도 의도한 목적을 제대로 이루지 못했다.
여기서 큰 문제점은 clone 메서드가 선언된 곳이 Cloneable이 아닌 OBject이고,
그 마저도 protected이다. 그래서 Cloneable을 구현하는 것만으로는 외부 객체에서
clone 메소드를 호출할 수 없다. 리플렉션을 사용하면 가능하지만, 100% 성공하는 것도 아니다.
이러한 여러 문제점을 가진 인터페이스이지만,
Cloneable 방식은 널리 쓰이고 있어서 잘 알아두는 것이 좋다.
Cloneable이 몰고 온 모든 문제를 되짚어봤을 때, 새로운 인터페이스를 만들 때는 절대
Cloneable을 확장해서는 안 되며, 새로운 클래스도 이를 구현해서는 안된다.
final 클래스라면 Cloneable을 구현해도 위험이 크지는 않지만,
성능 최적화 관점에서 검토한 후 별다른 문제가 없을 때만 드물게 허용해야 한다.
기본 원칙은 '복제 기능은 생성자와 팩터리를 이용하는게 최고' 라는 것이다.
단, 배열만은 clone 메소드 방식이 가장 깔끔한, 이 규칙의 합당한 예외라 할 수 있다.
http://www.yes24.com/Product/Goods/65551284
복사 생성자는 단순히 자신과 같은 클래스의 인스턴스를 파라미터로 받는 생성자를 말한다.
public Person(Person targetPerson) {
this.name = targetPerson.getName();
this.age = targetPerson.getAge();
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("person", 26);
Person copyPerson = new Person(person);
System.out.println(person);
System.out.println(copyPerson);
System.out.println();
System.out.println(person.getName());
System.out.println(copyPerson.getName());
System.out.println(person.getAge());
System.out.println(copyPerson.getAge());
}
}
p0000.Person@2133c8f8
p0000.Person@43a25848
person
person
26
26
public static Person copy(Person targetPerson) {
return new Person(targetPerson.getName(), targetPerson.getAge());
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("person", 26);
Person copyPerson = Person.copy(person);
System.out.println(person);
System.out.println(copyPerson);
System.out.println();
System.out.println(person.getName());
System.out.println(copyPerson.getName());
System.out.println(person.getAge());
System.out.println(copyPerson.getAge());
}
}
p0000.Person@2133c8f8
p0000.Person@43a25848
person
person
26
26

