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

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

要实现这一功能,可以使用Object类中的clone方法。clone方法可以完成对象的浅克隆。所谓浅克隆就是说被克隆的对象的各个属性都是基本类型,而不是引用类型(接口、类、数组),如果存在引用类型的属性,则需要进行深克隆。

1.浅克隆

编写一个 Address类,state(国家)、province(省)、city(市),然后再构造方法中初始化这三个值,并提供 getter()和setter()方法,用于修改这三个字段,最后重写toString()来输出该类的对象,代码如下:

public class Address{
    private String state;
    private String province;
    private String city;

    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() {
        return "Address{" +
                "state='" + state + '\'' +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}


编写一个类Employee,定义name、age、address,在构造方法中初始化这三个字段,同样实现getter()和setter()和 toString(),然后实现 Cloneable接口,最后重写clone方法来提供克隆的功能。

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 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() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

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

编写 Text 类来进行测试下:
@Test
public void test(){
    System.out.println("克隆之前");
    Address address = new Address("中国", "河北省", "沧州市");
    Employee employee = new Employee("马苏", 32, address);
    System.out.println("员工 1 的信息 ==> "+ employee);

    System.out.println("克隆之后");
    Employee employee1 = employee.clone();
    employee1.getAddress().setState("中国");
    employee1.getAddress().setProvince("天津");
    employee1.getAddress().setCity("北辰区");
    employee1.setName("王丽坤");
    employee1.setAge(33);
    System.out.println("员工 2 的信息 ==> "+ employee1);

    System.out.println("员工 1 的信息 ==> "+ employee);
}
结果如下图:

在这里插入图片描述
会发现一个问题,第一个员工对象的名字年龄和第二个员工对象的名字年龄不一致,说明name(基本类型)和age(基本类型)克隆成功,即修改第二个员工的名字和年龄不会影响到第一个员工的名字和年龄。但是,我修改完第二个员工的地址后发现第一个员工的地址也发生了变化,说明 Address(引用类型)克隆不成功,即修改的是同一个对象,如果想把Address(引用类型)克隆成功,需要深克隆

深克隆

要想实现 Address的深克隆,首先让Address类实现 Cloneable 接口,重写clone方法

public class Address implements Cloneable{

    private String state;
    private String province;
    private String city;

    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() {
        return "Address{" +
                "state='" + state + '\'' +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }

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

在Employee类的clone方法里添加一行代码:employee.address = address.clone();

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 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() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

    @Override
    protected Employee clone(){
        Employee employee = null;
        try {
            employee = (Employee)super.clone();
            employee.address = address.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return employee;
    }
}
	编写测试类
	@Test
    public void test(){
        System.out.println("克隆之前");
        Address address = new Address("中国", "河北省", "沧州市");
        Employee employee = new Employee("马苏", 32, address);
        System.out.println("员工 1 的信息 ==> "+ employee);

        System.out.println("克隆之后");
        Employee employee1 = employee.clone();
        employee1.getAddress().setState("中国");
        employee1.getAddress().setProvince("天津");
        employee1.getAddress().setCity("北辰区");
        employee1.setName("王丽坤");
        employee1.setAge(33);
        System.out.println("员工 2 的信息 ==> "+ employee1);

        System.out.println("员工 1 的信息 ==> "+ employee);
    }

在这里插入图片描述
这次修改第二个员工的地址不会影响第一个员工的地址,说明深克隆成功。

总结:如果需要克隆的类中只有基本类型的话,那么只在该类中实现
Cloneable接口即可,如果该类中除了包含基本类型之外,还有引用类型的话,需要将该引用对象也要实现Cloneable接口,并重写clone方法。

  • 15
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Javaclone()方法是Object类定义的方法,它用于创建并返回当前对象的一个副本。这个副本就是一个新的对象,它与原始对象具有相同的属性和方法。通常情况下,我们需要在一个类实现clone()方法来支持对象克隆克隆对象是在Java处理对象的一种常见方式。通过克隆,我们可以在不修改原始对象的情况下创建该对象的一个副本。这在某些情况下是非常有用的,例如在多线程环境下,我们需要多个线程同时访问同一个对象,但是又不希望它们之间相互干扰。 在Java,要使用clone()方法来实现对象克隆,我们需要满足两个条件: 1. 实现Cloneable接口:这个接口是一个标记接口,它没有任何方法,只是用来标记一个类可以被克隆。 2. 重写clone()方法:这个方法是Object类的一个protected方法,需要在我们的类进行重写。在重写这个方法时,我们需要调用super.clone()方法来创建一个新的对象,并将原始对象的属性复制到这个新对象。 下面是一个示例代码,演示了如何在Java实现对象克隆: ``` public class MyClass implements Cloneable { private int value; public MyClass(int value) { this.value = value; } public int getValue() { return value; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 在这个示例代码,我们实现了一个MyClass类,并重写了clone()方法。在这个方法,我们调用了super.clone()方法来创建一个新的对象,并返回这个新对象。由于我们的类实现了Cloneable接口,因此它可以被克隆使用这个类进行克隆的代码如下: ``` MyClass obj1 = new MyClass(10); MyClass obj2 = (MyClass) obj1.clone(); System.out.println(obj1.getValue()); // 输出10 System.out.println(obj2.getValue()); // 输出10 ``` 在这个代码,我们创建了一个MyClass对象obj1,并将其克隆为obj2。由于这两个对象具有相同的属性和方法,因此它们的输出结果也是相同的。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值