欢迎访问宙启技术站
智能推送

Java中的对象克隆函数详解

发布时间:2023-06-22 01:48:54

Java中的对象克隆函数是指通过复制已有对象来创建一个新的对象,使得新对象和原对象的所有属性值、方法都相同。对象克隆函数在Java中具有很重要的作用,我们可以通过克隆函数来实现对象的复制或者备份,同时也可以提高程序的性能。

Java中的对象克隆函数通常有两种方式:浅克隆和深克隆。

1. 浅克隆

浅克隆会复制所有的基本类型属性,但是对于对象类型属性,只复制引用,不复制具体值。也就说,新对象中的引用和原对象相同,修改新对象的引用会影响原对象。因此,浅克隆在进行对象复制时,只有属性值为基本类型的类或者对属性值的修改可以被赋值到相应的变量上,而属性为对象类型的只能复制引用,而不是实际的值。

在Java中,对象提供了一个clone函数,利用这个函数可以轻松创建一个浅克隆对象。其语法如下:

Object clone() throws CloneNotSupportedException

需要注意的是,Java中的clone()方法是一个protected方法,如果想要克隆对象,必须对克隆函数进行重写,同时需要实现Cloneable接口,而且Cloneable接口是空接口,它只是一个标识作用,用于表明该类可以被克隆。

下面是实现浅克隆的示例代码:

public class Person implements Cloneable{
    private String name;
    private int age;
    private Address address;

    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    
    public Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Address address = new Address("Beijing", "China");
        Person person1 = new Person("Tom", 18, address);
        Person person2 = person1.clone();
        System.out.println(person1 == person2); // 输出false
        System.out.println(person1.getAddress() == person2.getAddress()); // 输出true
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

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

在上面的例子中,我们实现了Person类,其中包含name、age、address属性,address属性则是一个对象类型。在main函数中,我们创建了person1对象,其address属性指向address对象,然后使用person1的clone()方法创建了一个新的对象person2。通过比较person1和person2的地址,我们可发现两个对象的地址是不相同的,但是比较他们的引用值是相同的。因为我们只复制了address对象的引用,而没有复制其实际值。

2. 深克隆

深克隆会复制所有的基本类型和对象类型的属性,它对于对象类型的属性都采用递归方式,以保证对象属性能够正确地进行克隆。因此,新对象中的所有属性值与原对象均完全相等,但是占用的空间更大,效率也更低。

通常实现深克隆方式有三种:通过序列化实现、通过构造函数实现、通过对象的clone实现。

通过序列化实现深克隆,我们首先将原对象进行序列化操作,然后将序列化后的对象再进行反序列化操作即可,这样就完全脱离了原对象的影响。在Java中,实现序列化只需要实现Serializable接口即可。下面是通过序列化方式实现深克隆的示例代码:

public class Person implements Serializable {
    private String name;
    private int age;
    private Address address;

    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    
    public Person deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        // 将对象序列化
        oos.writeObject(this);
        // 将对象反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Person) ois.readObject();
    }

    public static void main(String[] args) throws ClassNotFoundException, IOException {
        Address address = new Address("Beijing", "China");
        Person person1 = new Person("Tom", 18, address);
        Person person2 = person1.deepClone();
        System.out.println(person1 == person2); // 输出false
        System.out.println(person1.getAddress() == person2.getAddress()); // 输出false
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

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

在上面示例中,我们重写了deepClone()方法进行深克隆的实现。使用ByteArrayOutputStream和ObjectOutputStream将对象进行序列化,然后使用ByteArrayInputStream和ObjectInputStream对序列化后的对象进行反序列化操作,这样就实现了深克隆。需要注意的是,为了实现序列化,必须保证Person和Address类都实现了Serializable接口。

通过构造函数实现深克隆,我们需要手动实现一个新对象,并将原对象所有属性赋值给新对象的属性,这样我们就可以创建一个新的完全与原对象相等的对象。下面是通过构造函数方式实现深克隆的示例代码:

public class Person {
    private String name;
    private int age;
    private Address address;

    public Person(Person person) {
        this.name = person.getName();
        this.age = person.getAge();
        Address address = person.getAddress();
        this.address = new Address(address.getProvince(), address.getCity());
    }
    
    public Person deepClone() {
        return new Person(this);
    }

    public static void main(String[] args) {
        Address address = new Address("Beijing", "China");
        Person person1 = new Person("Tom", 18, address);
        Person person2 = person1.deepClone();
        System.out.println(person1 == person2); // 输出false
        System.out.println(person1.getAddress() == person2.getAddress()); // 输出false
    }

    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

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

在上述示例代码中,我们通过构造函数进行深克隆的实现。重载了Person类的构造函数,将所有属性均赋值给新对象的属性,这样就创建了一个新的完全与原对象相等的对象。

3. 对象的clone实现深克隆

在上面的介绍中我们已经知道,Java对象提供了一个clone()方法,可以通过该方法创建浅克隆对象。而对于实现深克隆操作,我们就需要在重写clone方法时,对深度克隆进行调整。下面是实现深克隆的示例代码:

`

public class Person implements Clone