Java的对象克隆

克隆

直接使用new关键字创建的对象,是一个新的对象,没有任何数据(初始化的默认值)
使用克隆创建的对象,可以复制对象的数据
Java中数据类型有值类型(八大基本数据类型)和引用类型(类,数组,接口)
基本类型复制值,引用类型复制引用地址而不是对象本身
浅克隆、深克隆区别在于是否支持引用类型的成员变量的复制

1.1浅克隆 ShallowClone

  • 如果对象的成员变量是基本类型,克隆对象会拿到成员的值
  • 如果对象的成员变量是引用类型,克隆对象会拿到成员的引用地址

在浅克隆中:源对象和克隆对象的成员变量指向相同的内存地址

浅克隆实现:

1. 重写Object类的clone()方法
示例1

在这里插入图片描述
直接重写Object的clone(),会抛出异常

在这里插入图片描述
正确用法:1.先实现实现Cloneable接口,再重写clone()方法

在这里插入图片描述
测试
在这里插入图片描述

示例2

作为属性的类(没有重写clone方法)

public class Address{

    private String  address;

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

被克隆的类(重写了clone方法)

public class Person implements Cloneable {

    private String name;
    private Address address;

    public Person() {}

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

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

测试
在这里插入图片描述
两个对象关联的同一个Address对象,Address修改了,克隆对象的信息也发生了变化

2. 在spring中提供了BeanUtils.copyProperties(source,target);

1.2深克隆 DeepClone

在深克隆中,无论源对象的成员是基本类型/引用类型,都会复制给克隆对象
也就是在深克隆中,对象和所有成员都会被克隆
而在浅克隆中,只会克隆对象和基本类型成员的信息,和引用类型的地址

实现深克隆的方式

1、实现Cloneable接口,重写Object的clone()方法
  1. 原对象重写clone方法,在clone中,复制源对象和源对象的属性
  2. 原对象关联的对象重写clone方法

当做属性的类(重写clone方法)

public class Address implements Cloneable {

    private String address;

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

    @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }
}

被克隆的类(重写clone方法)

package com.example.java_hign.clone.demo2;

public class Person implements Cloneable {

    private String name;
    private Address address;

    public Person() {}

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

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        //深度克隆  连同person中关联的对象也一同克隆.
        person.address = (Address) address.clone();   
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

测试

public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new Person("刘备",address);

        Person p2 =p1.clone();
               p2.setName("李世明");
               address.setAddress("西安");
		
        System.out.println(p1);// Person{name='刘备', address=Address{address='西安'}}
        //深度克隆:复制了源对象和源对象的关联对象,属性不再指向同一对象
        System.out.println(p2);//Person{name='李世明', address=Address{address='汉中'}}
    }
2、通过序列化实现(Serialization),不用在关联的对象中也重写Clone()

被关联的类Address(实现Serializable 序列化接口)

public class Address  implements Serializable {

    private String  address;

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

被克隆的源对象(实现Serializable 序列化接口)

public class Person implements Serializable {

    private String name;
    private Address address;

    public Person() {}

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

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    /**
     * 自定义克隆方法
     */
    public Person myclone() {
        Person person = null;
        try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);
            // 将流序列化成对象
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            person = (Person) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

测试
在这里插入图片描述

总结:

  • 浅克隆中,克隆对象的引用对象和原对象使用的同一个对象
  • 深克隆中,克隆对象的引用对象都是重新创建的对象
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的对象克隆工具类是指能够帮助我们实现对象克隆操作的工具类。 在Java中,对象克隆是指创建一个与原始对象具有相同属性和值的新对象。这个新对象可以是原始对象的完全副本,即改变新对象不会影响原始对象。为了实现对象克隆Java提供了Cloneable接口和clone()方法。 下面是一个简单的Java对象克隆工具类的示例代码: ``` public class CloneUtil { public static <T> T clone(T source) { try { // 判断对象是否实现了Cloneable接口 if (source instanceof Cloneable) { // 通过调用clone()方法进行对象克隆 Method cloneMethod = source.getClass().getMethod("clone"); return (T) cloneMethod.invoke(source); } } catch (Exception e) { e.printStackTrace(); } return null; } } ``` 在上面的代码中,我们定义了一个泛型方法clone(),它接受一个参数source,表示要克隆的原始对象。然后我们首先使用instanceof运算符来判断source是否实现了Cloneable接口,如果是,则通过反射获取clone()方法,并调用它来进行对象克隆。最后返回克隆后的新对象。 使用该工具类进行对象克隆的示例代码如下: ``` public class Main { public static void main(String[] args) { Person person1 = new Person("Alice", 25); // 使用克隆工具类进行对象克隆 Person person2 = CloneUtil.clone(person1); System.out.println(person1); System.out.println(person2); System.out.println(person1 == person2); } } ``` 在上面的示例代码中,我们创建了一个Person对象person1,并将其克隆到person2中。然后分别打印person1、person2以及判断person1和person2是否为同一个对象。 通过上述Java对象克隆工具类的实现,我们可以方便地实现对象克隆操作,提高代码的可复用性和效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值