Object浅拷贝、深拷贝

将一个对象的引用复制给另外一个对像三个方式:1.直接赋值、2.浅拷贝、3.深拷贝

1.直接赋值:赋值的是引用。

2.浅拷贝定义(shallow clone):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

3.深拷贝(deep clone):被复制对象的所有变量都含有与原来的对象相同的值,把要复制的对象所引用的对象都复制了一遍。 


直接赋值例子:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:31
 */
public class Student {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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


测试:

/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:06
 */
public class CloneTest {
    public static void main(String[] args) {
        Student s=new Student("s");
        Student ss=s;
        ss.setName("ss");
        System.out.println("s对象的姓名..."+s.getName());
    }

}

结果:

s对象的姓名...ss

结论:直接赋值是对象引用,也就是说多个对象引用同一个,任何一个对象改变引用,那么其他对象的内容跟着变(本例子中,s对象的姓名“s”,被ss对象改变了)


浅拷贝例子:实现Cloneable接口,该接口没有任何方法


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:31
 */
public class Student implements  Cloneable{
    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
//不是重写方法,Cloneable没有任何方法
    public Student clone() {
        try {
            return (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}


测试:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:06
 */
public class CloneTest {
    public static void main(String[] args) {
        Student s=new Student("s");
        Student ss=s.clone();
        ss.setName("ss");
        System.out.println("s对象的姓名..."+s.getName());
    }

}


结果:

s对象的姓名...s

ss改变了对象name,但是s对象name没有变。

结论:利用浅拷贝,相当于创建一个对象。但是如果对象里面包含另外一个对象引用呢?结果如何


浅拷贝的复杂对象的例子:


对象Student:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:31
 */
public class Student implements  Cloneable{
    private String name;
    private StudentClass studentClass;//添加了一个对象引用

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public StudentClass getStudentClass() {
        return studentClass;
    }

    public void setStudentClass(StudentClass studentClass) {
        this.studentClass = studentClass;
    }

    public Student clone() {
        try {
            return (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}


对象StudentClass:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 下午 12:54
 */
public class StudentClass {
    /**
     * 班级编号
     */
    private String number;

    public StudentClass(String number) {
        this.number = number;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

测试代码:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:06
 */
public class CloneTest {
    public static void main(String[] args) {
        Student s = new Student("s");
        s.setStudentClass(new StudentClass("1班"));
        Student ss = s.clone();
        ss.setName("ss");
        ss.getStudentClass().setNumber("2班");
        System.out.println("s对象的姓名..." + s.getName());
        System.out.println("s对象的班级..." + s.getStudentClass().getNumber());
    }

}

结果:

s对象的姓名...s
s对象的班级...2班


s对象的班级编号,还是被ss对象改变了。如果面对复杂的对象中(对象嵌套对象,怎么办?)


深度拷贝:


Student对象:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:31
 */
public class Student implements Cloneable {
    private String name;
    private StudentClass studentClass;

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public StudentClass getStudentClass() {
        return studentClass;
    }

    public void setStudentClass(StudentClass studentClass) {
        this.studentClass = studentClass;
    }

    public Student clone() {
        Student s = null;
        try {
            s = (Student) super.clone();
            s.studentClass = s.getStudentClass().clone();//将引用的对象也加上
            return s;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }


StudentClass对象:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 下午 12:54
 */
public class StudentClass implements Cloneable {
    /**
     * 班级编号
     */
    private String number;

    public StudentClass(String number) {
        this.number = number;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public StudentClass clone() {
        try {
            return (StudentClass) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }

    }
}

测试:


/**
 * Description:
 * User: lc
 * Date: 2017/10/6 0006
 * Time: 上午 11:06
 */
public class CloneTest {
    public static void main(String[] args) {
        Student s = new Student("s");
        s.setStudentClass(new StudentClass("1班"));
        Student ss = s.clone();
        ss.setName("ss");
        ss.getStudentClass().setNumber("2班");
        System.out.println("s对象的姓名..." + s.getName());
        System.out.println("s对象的班级..." + s.getStudentClass().getNumber());   
    System.out.println("s对象的hsahCode..."+s.toString());
   System.out.println("ss对象的hsahCode..."+ss.toString());
 }}

 


测试结果:


s对象的姓名...s
s对象的班级...1班
s对象的地址...object.objectClone.Student@28d93b30
ss对象的地址...object.objectClone.Student@1b6d3586
ss对象的改变,没有影响到s对象.两个不同对象,地址不一样


总结:
     1. 需要实现Cloneable接口。Cloneable接口里面没任何方法。会抛出 CloneNotSupportedException.重写clone方法(因为Object是任何类的父类)
     2.Object的clone方法是protect,本地方法(native).
     3.如果对象嵌套对象,很复杂的情况,用深度拷贝,不合适,这样时候需要用序列化以及反序列化。


备注:继承自java.lang.Object类的clone()方法是浅复制。
   


克隆与new的区别:
      1.clone可以保存当时对象的状态。而new只能进行初始化状态。
       2.clone调用的是本地方法,速度更快





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值