딥 클론 및 얕은 클론

클론이 필요한 이유는 무엇입니까?new에서 나온 대상의 속성은 모두 초기화할 때의 값이다. 현재 대상의'상태'를 저장하기 위해 새로운 대상이 필요하다면 clone 방법에 의존한다.그냥 Object a=new Object();Object b;b=a쓰면 안 돼요? 답은 안 돼요.인용만 복제했기 때문이다.
클론은 어떻게 구현됩니까?
먼저 두 가지 복제 방식이 있는데 하나는 심층 복제이고 하나는 얕은 복제이다.그들 사이의 차이점은 인용 유형의 구성원 변수 복제를 지원하는지 여부입니다. 깊은 클론은 인용 유형의 구성원 변수를 복제합니다.clone 방법은 Object에서 유래한 것이다. 우리는 본원을 추적해 보자.
 protected native Object clone() throws CloneNotSupportedException;
이를 통해 알 수 있듯이 clone()Objectnative 방법이고 protected는 더 이상 유외적으로 접근할 수 없다고 생각하여 복제 방법을 실현하려면 이 방법을 덮어쓰는 수밖에 없다.
public class Student implements Cloneable {
    private String name;
    private int age;
    
    @Override
    protected Object clone()  {
        Student student=null;
        try {
            student =(Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;

    }
   ...
   getter and setter
   ...
public class Test {
    public static void main(String[] args){
        Student stu1 = new Student(" ",18);
        Student stu2 = (Student) stu1.clone();
        
        stu2.setName(" ");
        stu2.setAge(20);
        System.out.println("stu1:"+stu1.getName()+" age:"+stu1.getAge());
        System.out.println("stu2:"+stu2.getName()+" age:"+stu2.getAge());
        System.out.println(stu2 == stu1);  //false
    }
}
stu1:  age:18
stu2:  age:20
false
상기 사례는 얕은 복제에 속하고 복제 대상의 속성은 인용 대상을 포함하지 않으며 인용 대상을 포함하면 이 인용 대상도 반드시cloneable 인터페이스를 실현해야 한다.
public class Student implements Cloneable {
    private String name;
    private int age;
    private Address address;        // 
    
    @Override
    protected Student clone()  {
        Student stu =null;
        try {
            stu = (Student) super.clone();
            stu.setAddress(address.clone());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return stu;
    }
    ....
public class Address implements Cloneable {
    private String add;
    
    // clone 
    @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }
    ....
}
public class Test {
    public static void main(String[] args){
        Student stu1 = new Student(" ",18,new Address(" "));
        Student stu2 = (Student) stu1.clone();

        stu2.setName(" ");
        stu2.setAge(20);
        stu1.setAddress(new Address(" "));
        System.out.println("stu1:"+stu1.getName()+" age:"+stu1.getAge()+"address"+stu1.getAddress().getAdd());
        System.out.println("stu2:"+stu2.getName()+" age:"+stu2.getAge()+"address"+stu2.getAddress().getAdd());
    }
}
stu1:  age:18address 
stu2:  age:20address 
인용 유형에 많은 인용 유형이 포함되어 있거나 내부 인용 유형의 클래스에 인용 유형이 포함되어 있으면 clone 방법을 사용하면 번거롭다.이때 우리는 서열화된 방식으로 대상의 깊은 복제를 실현할 수 있다.
public class Student implements Serializable {
    private static final long serialVersionUID = -3950409490183038226L;

    private String name;
    private int age;
    private Address address;
    
    public Student CloneObject(Object obj){
        Student student = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);

            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
             student = (Student) ois.readObject();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return student;
    }
......
public class Address implements Serializable {

    private static final long serialVersionUID = -4265312082191071263L;
    private String add;

    @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }
    .....
}
public class Test {
    public static void main(String[] args){
        Student stu1 = new Student(" ",18,new Address(" "));
        Student stu2 = stu1.CloneObject(stu1);

        stu2.setName(" ");
        stu2.setAge(20);
        stu1.setAddress(new Address(" "));
        System.out.println("stu1:"+stu1.getName()+" age:"+stu1.getAge()+"address"+stu1.getAddress().getAdd());
        System.out.println("stu2:"+stu2.getName()+" age:"+stu2.getAge()+"address"+stu2.getAddress().getAdd());
    }
}
stu1:  age:18address 
stu2:  age:20address 

요약:
객체 복제를 수행하는 방법은 다음과 같습니다. 1).Cloneable 인터페이스를 실현하고 Object 클래스의 Clone () 방법을 다시 쓰기;
2). Serializable 인터페이스를 실현하고 대상의 서열화와 반서열화를 통해 복제를 실현하면 진정한 깊이 복제를 실현할 수 있다.
참고:
서열화와 반서열화를 바탕으로 이루어진 복제는 깊이 있는 복제만이 아니라 범용 제한을 통해 복제할 대상이 서열화를 지원하는지 확인할 수 있다. 이 검사는 컴파일러가 완성한 것이지 실행할 때 이상을 던지는 것이 아니다. 이런 방안은 Object류의 clone 방법으로 복제하는 대상보다 현저히 우수하다.문제를 컴파일할 때 노출시키는 것이 항상 문제를 실행할 때까지 남겨 두는 것보다 낫다.

좋은 웹페이지 즐겨찾기