java深克隆与浅克隆

java中对象的复制分为深克隆与浅克隆

浅克隆:

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

深克隆:

与浅克隆相对应的。被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

1.浅克隆:

 首先我们来看看Object类中clone方法

protected Object clone()
                throws CloneNotSupportedException
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式:
x.clone() != x
为 true,表达式:
x.clone().getClass() == x.getClass()
也为 true,但这些并非必须要满足的要求。一般情况下:
x.clone().equals(x)
true,但这并非必须要满足的要求。

按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()

按照惯例,此方法返回的对象应该独立于该对象(正被复制的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被复制对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。

Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意,所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我复制。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。 


根据上面所说的,浅克隆就是重写Object类得clone方法,重写方法时调用super.clone(),识别出你要调用的哪个对象,同时还需要实现Cloneable接口,查看源代码时可以发现,这个接口没有任何方法,与Serializable一样也是一个标识性的接口。


2.深克隆:引用类型的实例变量也需要复制一遍,所以我们可以在clone方法中,把引用类型实例变量也按照浅克隆的方法克隆一遍,如果有多个对象,这样显然比较繁琐,这里有一种方法是利用序列化,因为实现序列化的类,其中的引用类型的变量也需要实现序列化,把对象写到流里就是序列化的过程,我们反序列化,把对象从流里读出来,就可以重建对象,实现深克隆。

以下是示例代码:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class CloneTest {
    public static void main(String[] args) throws Exception {
        Student student = new Student();
        Teacher teacher = new Teacher();
        teacher.setAge(30);
        teacher.setName("Miss li");
        
        student.setAge(11);
        student.setName("zhang san");
        student.setTeacher(teacher);
        
        
        Student student2 = (Student) student.deepClone();
        System.out.println(student2.getAge()+" "+student2.getName()+" "+student2.getTeacher().getName());
        
        System.out.println("-------------------------------");
        
        teacher.setName("Miss zhao");
        System.out.println(student2.getAge()+" "+student2.getName()+" "+student2.getTeacher().getName());
    }
}

class Student implements Cloneable,Serializable{
    /**
     * 序列化ID
     */
    private static final long serialVersionUID = 8566811282124767945L;
    private int age;
    private String name;
    private Teacher teacher;
    
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    //浅克隆
    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
      
    }
    //深克隆
    public Object deepClone() throws Exception{
       //将对象写到流里    
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
      //从流里读出来  
        InputStream is = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(is);
        return ois.readObject();
    }
    
    
}
class Teacher implements Serializable{
    /**
     * 序列化ID
     */
    private static final long serialVersionUID = -2380977769309339400L;
    private int age;
    private String name;
    
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值