Java 中如何使用clone()方法克隆对象?

时间:2023-01-02 09:36:20

java为什么要 对象克隆:

 

在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变。这时,如果使用Java 提供的对象赋值语句,当修改B 对象的属性值后,A 对象的属性值也将被修改。那么应该如何实现创建一个与A 对象完全相同的B 对象,但是改变B对象的属性值时A 对象的属性值不变呢?

 

专家解答

要实现这一功能,可以使用Object 类中的clone()方法。clone()方法可以用来完成对象的浅克隆。所谓浅克隆就是说被克隆的对象各个属性都是基本类型,而不是引用类型。如果存在引用类型的属性,则需要进行深克隆。下面对这两种克隆方式进行举例说明。

1.浅克隆(1)编写Address 类,首先在该类中定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,最后重写toString()方法方便输出该类的对象,代码如下:

 

 

 

1.浅克隆(1)编写Address 类,首先在该类中定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,最后重写toString()方法方便输出该类的对象,代码如下:

地址对象:

package com.nf147.Constroller;

public class Address implements Cloneable {
    private String state;            //国家
    private String province;         //
    private String city;            //市

    public Address() {
    }

    public Address(String state, String province, String city) {
        this.state = state;
        this.province = province;
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {                  //重写toString
        StringBuilder sb=new StringBuilder();
        sb.append("国家:"+state+",");
        sb.append("省:"+province+",");
        sb.append("市:"+city+",");
        return sb.toString();
    }
}

 

 编写Employee 类,首先在该类中定义name(表示姓名)、age(表示年龄)和address(表示地址)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法来提供克隆的功能,代码如下:

员工:

package com.nf147.Constroller;

public class Employee implements Cloneable {

    private String name;        //姓名
    private int age;            //年龄
    private Address address;    //地址

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

    public Employee() {
    }

    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;
    }

    @Override
    public String toString() {   //重新toString()方法
        return "Employee{" +
                "姓名='" + name + '\'' +
                ", 年龄=" + age +
                ", 地址=" + address +
                '}';
    }

    public Employee clone() {           //实现浅克隆
        Employee employee = null;
        try {
            employee = (Employee) super.clone();
            employee.address = address.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return employee;
    }


}

 

测试类:

package com.nf147.Constroller;

public class TestClone {
    public static void main(String[] args) {
        System.out.println("克隆之前:");
        Address address = new Address("中国", "吉林", "长春");
        Employee employee1 = new Employee("无语", 32, address);
        System.out.println("员工 1 的信息");
        System.out.println(employee1);

        System.out.println("====================");
        System.out.println("克隆之后:");

        Employee employee2=employee1.clone();
        employee2.getAddress().setState("中国");
        employee2.getAddress().setProvince("辽宁");
        employee2.getAddress().setCity("大连");
        employee2.setName("倾城");
        employee2.setAge(33);
        System.out.println("员工2 的 信息");
        System.out.println(employee2);
        System.out.println("员工1的 信息");
        System.out.println(employee1);
    }
}

 

 

 

说明:

从图中可以看到,对于引用类型并没有克隆成功。

 

2.深克隆(1)编写类Address1,在该类中首先定义state(表示国家)、province(表示省)和city(表示市)3 个域,然后在构造方法中初始化这3 个域,并提供了getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法提供克隆的功能,关键代码如下:

package com.nf147.Constroller;

public class Address implements Cloneable {
    private String state;            //国家
    private String province;         //
    private String city;            //市

    public Address() {
    }

    public Address(String state, String province, String city) {
        this.state = state;
        this.province = province;
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {                  //重写toString
        StringBuilder sb=new StringBuilder();
        sb.append("国家:"+state+",");
        sb.append("省:"+province+",");
        sb.append("市:"+city+",");
        return sb.toString();
    }

    @Override
    protected Address clone(){
        Address address = null;
        try{
            address=(Address)super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return address;
    }
}

 

说明:

Address 类的域不是基本类型就是不可变类型,所以可以直接使用浅克隆。

(2)编写Employee类,首先在该类中定义name(表示姓名)、age(表示年龄)和address(表示地址)3 个域,然后在构造方法中初始化这3 个域,并提供getter()和setter()方法用于获得和修改这3 个域,再重写toString()方法方便输出该类的对象,最后重写clone()方法来提供克隆的功能。代码如下:

 

package com.nf147.Constroller;

public class Employee implements Cloneable {

    private String name;        //姓名
    private int age;            //年龄
    private Address address;    //地址

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

    public Employee() {
    }

    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;
    }

    @Override
    public String toString() {   //重新toString()方法
        return "Employee{" +
                "姓名='" + name + '\'' +
                ", 年龄=" + age +
                ", 地址=" + address +
                '}';
    }

    public Employee clone() {           //实现浅克隆
        Employee employee = null;
        try {
            employee = (Employee) super.clone();
            employee.address = address.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return employee;
    }


}

测试:

package com.nf147.Constroller;

public class TestClone {
    public static void main(String[] args) {
        System.out.println("克隆之前:");
        Address address = new Address("中国", "吉林", "长春");
        Employee employee1 = new Employee("无语", 32, address);
        System.out.println("员工 1 的信息");
        System.out.println(employee1);

        System.out.println("====================");
        System.out.println("克隆之后:");

        Employee employee2=employee1.clone();
        employee2.getAddress().setState("中国");
        employee2.getAddress().setProvince("辽宁");
        employee2.getAddress().setCity("大连");
        employee2.setName("倾城");
        employee2.setAge(33);
        System.out.println("员工2 的 信息");
        System.out.println(employee2);
        System.out.println("员工1的 信息");
        System.out.println(employee1);
    }
}