以前也用过这个接口,那时是直接所有的东西都自己写了,也没发现问题。最近无意间发现这个接口的实现并不是想象中的那样,所以稍微研究了下,给大家分享一下。

步骤:1、建立两个简单的POJO:Teacher和Student

      2、Teacher类实现了Cloneable接口,重写clone方法

      3、在main方法中建立teacher,然后clone,比较teacher和clone出来的teacher

 Teacher类:

public class Teacher implements Cloneable,Serializable{

    private String name;
    
    private String sex;
    
    private int age;
    
    private List<Student> list;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public List<Student> getList() {
        return list;
    }

    public void setList(List<Student> list) {
        this.list = list;
    }
    
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Teacher clone() throws CloneNotSupportedException {
        
        Teacher t = (Teacher)super.clone();
        
        return t;
    }
    
    public Teacher deepClone() throws IOException, ClassNotFoundException
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        ObjectOutputStream temp_out = new ObjectOutputStream(out);  
        temp_out.writeObject(this);  
 
        ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray());  
        ObjectInputStream temp_input = new ObjectInputStream(input);  
        return (Teacher) temp_input.readObject();
    }
}


Student类:

public class Student implements Serializable{

    private String stName;
    
    private String stSex;

    public String getStName() {
        return stName;
    }

    public void setStName(String stName) {
        this.stName = stName;
    }

    public String getStSex() {
        return stSex;
    }

    public void setStSex(String stSex) {
        this.stSex = stSex;
    }
}


main:

public class MainTest {

    public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
       List<Student> list = new ArrayList<Student>();
        
        Student st = new Student();
        
        st.setStName("stname");
        
        st.setStSex("f");
        
        list.add(st);
        
        Teacher te = new Teacher();
        
        te.setAge(19);
        
        te.setList(list);
        
        te.setName("tename");
        
        te.setSex("tesex");
        
        Teacher cl = te.clone();
        
        cl.setAge(12);
        
        System.out.println("淺複製"+ (cl == te));
        
        //内存中的地址
        System.out.println(cl.getName() == te.getName());
        
        System.out.println(cl.getList() == te.getList());
        
        System.out.println("source:"+te.getAge()+"<==>clone:"+cl.getAge());

     
        
        Teacher  deep = te.deepClone();


         System.out.println("深複製"+(cl == te));

        
        System.out.println(deep.getName() == te.getName());
        
        System.out.println(deep.getList() == te.getList());

    }
}

输出结果:

淺複製false
true
true
source:19<==>clone:12
深複製false
false
false

从输出结果可以得出的结论

1、对于浅复制来说,当调用clone方法返回的cl对象跟te对象不是同一个对象(地址不一样),但是内部的对象引用却是引用的相同对象(地址一样);而对于基本类型age(int)来说,克隆的对象cl跟原始对象te不是同一个(如果是同一个的话,修改任何一个,另外对象的内容也会变化)

2、对于深复制来说,克隆出来的对象不但跟原始对象不一样(地址不一样),而且内部应用对象也不一样了(地址不一样)