浅克隆与深克隆

1.浅克隆(shallow clone)

被复制对象的所有基础类型变量(byte,short,int,long,char,boolean,float,double)与原有对象中变量具有相同的值,修改其值不会影响原对象;而复制对象中引用类型(数组,类对象等)还是指向原来对象,修改其值会影响原对象。

2.深克隆(deep clone)

被复制对象的所有基础类型变量(byte,short,int,long,char,boolean,float,double)与原有对象中变量具有相同的值,修改其值不会影响原对象;并且复制对象中引用类型(数组,类对象等)指向被复制过的新对象,修改其值不会影响原对象。

java.lang.Object 类包含 clone()方法:

protected native Object clone() throws 
CloneNotSupportedException;  

// 1.native方法,本地方法,效率高于非native方法。
// 2.访问修饰符protected,Object子类可以使用clone(),同时为了其它类可以调用clone(),必须将Object子类重写的clone()访问修饰符改为public。
// 3.clone()返回Object,需强制类型转换

对任何对象x, x.clone() != x; 不是同一个对象

被克隆的对象都是通过super.clone()方法获取当前对象的副本;当前对象必须实现了Cloneable接口,否则会抛出CloneNotSupportedException。

浅克隆实例:

class Employer {
    private String employerName;
    int age;


    public int getAge() {
        return age;
    }

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

    public String getEmployerName() {
        return employerName;
    }

    public void setEmployerName(String employerName)        {
        this.employerName = employerName;
    }
    public Employer(String employerName, int age){
        this.employerName = employerName;
        this.age = age;
    }

}


class Employee implements Cloneable{
    private String employeeName;
    private Employer employer;

    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    public Employer getEmployer() {
        return employer;
    }

    public void setEmployer(Employer employer) {
        this.employer = employer;
    }

    public Employee(String employeeName, Employer employer){
        this.employeeName = employeeName;
        this.employer = employer;
    }

    public Object clone() throws    CloneNotSupportedException {
        Employee employee = (Employee)super.clone();
        return employee;
    }
}


public class TestShallowClone{

public static void main(String[] args) throws CloneNotSupportedException {
    Employer employer = new Employer("Jack", 30);
    Employee employee = new Employee("John", employer);

    Employee emeClone = (Employee) employee.clone();

    emeClone.getEmployer().setEmployerName("Tom");

    System.out.println(emeClone.getEmployer().getEmployerName());
    // 浅克隆对象的改变影响了被克隆对象System.out.println(employee.getEmployerer().getEmployerName());

    System.out.println((employee.getEmployer() == emeClone.getEmployer()) ? ("浅克隆") : ("深克隆"));

    }   

}

输出:

Tom
Tom
浅克隆

两个引用(employee.getEmployer() 和 emeClone.getEmployer())所指向的对象在堆中一致,互相影响,浅克隆。

深克隆实例

class Employer implements Cloneable{
    private String employerName;
    int age;


    public int getAge() {
        return age;
    }

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

    public String getEmployerName() {
        return employerName;
    }

    public void setEmployerName(String employerName) {
        this.employerName = employerName;
    }
    public Employer(String employerName, int age){
        this.employerName = employerName;
        this.age = age;
    }

    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }

}


class Employee implements Cloneable{
    private String employeeName;
    private Employer employer;

    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    public Employer getEmployer() {
        return employer;
    }

    public void setEmployer(Employer employer) {
        this.employer = employer;
    }

    public Employee(String employeeName, Employer employer){
        this.employeeName = employeeName;
        this.employer = employer;
    }

    public Object clone() throws CloneNotSupportedException {
        Employee employee = (Employee)super.clone();
        employee.employer = (Employer)employer.clone();
        return employee;
    }
}


public class TestDeepClone{

    public static void main(String[] args) throws CloneNotSupportedException {
        Employer employer = new Employer("Jack", 30);
        Employee employee = new Employee("John", employer);

        Employee emeClone = (Employee) employee.clone();

        emeClone.getEmployer().setEmployerName("Tom");

        System.out.println(emeClone.getEmployer().getEmployerName());
        // 深克隆对象的改变不影响被克隆对象 
        System.out.println(employee.getEmployer().getEmployerName());
        System.out.println((employee.getEmployer() == emeClone.getEmployer()) ? ("浅克隆") : ("深克隆"));

    }
}   

输出:

Tom
Jack
深克隆

两个引用(employee.getEmployer() 和 emeClone.getEmployer())所指向的对象在堆中相互独立,互不影响,深克隆。

总结:

1.被克隆的对象必须实现java.lang.Cloneable接口。

2.在克隆对象时,不调用构造函数。

3.浅克隆是在创建好对象副本后通过赋值进行拷贝,如果对象中包含引用类型,那么原始对象和克隆对象都指向相同的堆内存,对克隆对象任何修改都会影响到原始对象;必须使用深克隆,引用类型对象也需实现java.lang.Cloneable接口,重写clone(), 原始对象中clone()方法需将原始对象的引用类型成员赋值为引用对象的clone()。

4.对于基本类型byte,char,boolean,short,int,long,float,double会进行值拷贝,而对引用类型和数组,则是地址拷贝(也叫引用拷贝),就是指在新的对象中声明一个引用,该引用的地址指向被拷贝对象中的对应的成员的地址。

5.emeClone.setEmployeeName(“Hank”) 只是将emeClone的employeeName指向另一个String对象“Hank”,查看employee.getEmployeeName()还是为“John”;java中String对象是不可变的,一旦创建,就不能修改它的值;如果一个类的成员变量是基本类型和String类型,调用Object的clone()是安全的克隆。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值