为什么使用对象拷贝(克隆)

当一个对象不够用的时候,如页面要分别显示老师和学生的信息,我们可以先new一个老师teacher对象,然后使用对象拷贝或者克隆的方式创建一个学生student对象。

//伪代码
Person teacher = new Person("张三老师","男","xxx学院");
Person student = CopyfromPerson(teacher);
student.setName("李四学生");

在上面的例子中,张三老师和李四学生就是名字不一样,其它的两个字段可以一样,所以我们可以拷贝 teacher对象创建student对象。

如何实现对象拷贝(克隆Cloneable接口)

1) 实现Cloneable接口的浅拷贝,浅拷贝中的类只包含基本数据类型。

定义一个简单的Person类,并实现克隆接口Cloneable。

class Person implements Cloneable{
    private String name ;
    private String sex;
    private String college;

    /**
     * 浅拷贝或者浅克隆
     * @return
     */
    @Override
    public Object clone() {
        Person person = null;
        try{
            person = (Person) super.clone();
        }catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return person;
    }

    public Person() {
    }

    public Person(String name, String sex, String college) {
        this.name = name;
        this.sex = sex;
        this.college = college;
    }

    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 String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }
}
调用拷贝方法。

public class CloneExample {

    public static void main(String[] args) {
        Person teacher = new Person("张三老师","男","xxx学院");
        Person student = (Person) teacher.clone();//浅拷贝
        System.out.println(teacher);
        System.out.println(student);

    }
}

测试一下

从输出结果中我们看到teacher和student对象的地址不一样。

这里的clone对象相当于完全复制了一个新的对象,新的对象有它自己的地址,修改原来的对象新对象不变。不过这里是浅拷贝,只拷贝的对象第一层属性。对于有多层级的对象(深拷贝),该方法就不成立了,下面看clone的深拷贝。

2) 实现Cloneable接口的深拷贝,深拷贝中的类包含非基本数据类型。

这里给Person类增加一个Address类,如下:

class Address implements Cloneable{
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    private String name ;
    private String sex;
    private String college;
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    /**
     * 深拷贝
     * @return
     */
    @Override
    public Object clone() {
        Person person = null;
        try{
            person = (Person) super.clone();
            person.address = (Address) address.clone();
        }catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return person;
    }

    public Person() {
    }

    public Person(String name, String sex, String college) {
        this.name = name;
        this.sex = sex;
        this.college = college;
    }

    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 String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }
}
调用拷贝方法
public class CopyExample2{

    public static void main(String[] args) {
        Person teacher = new Person("张三老师","男","xxx学院");
        Address address = new Address();
        address.setAddress("湖北 武汉");
        teacher.setAddress(address);
        Person student = (Person) teacher.clone();//浅拷贝
        System.out.println(teacher);
        System.out.println(student);

    }
}

深拷贝和浅拷贝区别是什么

他们的区别就是实现Cloneable接口的类中是否包含其他的类。

  • 实现Cloneable接口的类中只包含基本数据类型则是浅拷贝
  • 实现Cloneable接口的类中包含非基本数据类型则是深拷贝
说的再直白点就是浅拷贝只拷贝对象的第一层属性,深拷贝拷贝对象的多层属性。