对象的克隆

目录

对象的克隆

java当中的克隆跟生物上所说的克隆类似,就是复制出一个一模一样的个体,当然迁移到java当中,那就是复制出一个一模一样对象,别忘了java当中有句话叫做一切皆对象。通过克隆就能提高对象的独立性,使用起来更加方便,也更安全。


克隆的作用

对象克隆主要是为了解决引用类型在进行等号赋值时使得两个引用同时指向同一个对象实例,从而导致通过两个引用去操作对象时,会直接更改实例中的属性破坏对象的相互独立性。

//例如一下代码段
public class Test {

    public static void main(String[] args) {
        // TODO 
        Student s1 = new Student("Tom", 12);
        Student s2 = s1;//s2的引用指向s1
        System.out.println(s1);
        System.out.println(s2);
        s2.setName("Jerry");//修改s2的值时s1的属性
        System.out.println(s1);
        System.out.println(s2);
    }

上述代码运行的结果如图:
这里写图片描述

由上述运行结果可知,在引用类型当中,由于都是指向同一个对象实例,当我们用引用类型去修改对象实例的值时,原来对象的属性也会跟着改变,从而导致了数据的不一致性。对象的克隆就能解决上述问题,防止发生此类情况。

克隆的分类

浅克隆

浅克隆如下图所示,只适用于基本的数据类型,对于值传递就只是赋值,把所有属性都拿过来赋值给当前对象。当要克隆的对象里面存在另外一个非基本数据类型的对象实例时,由于只是简单地通过等号赋值,又相当于指向的是同一个实例对象,在进行修改时同样会修改原来的属性。
这里写图片描述

深度克隆

而深度克隆就是把对象的所有属性都统统复制一份新的到目标对象里面去,使他成为一个独立的对象,当修改新的对象实例的属性时,原来对象中的属性任然不变。
这里写图片描述

克隆的使用

浅克隆的使用

浅克隆的实现代码,例如:

package com.vince;
//实现Cloneable接口
public class Product implements Cloneable{
    private String name;
    private Integer price;
    public String getName() {
        return name;
    } 
    public void setName(String name) {
        this.name = name;
    }
    public Integer getPrice() {
        return price;
    }
    public void setPrice(Integer price) {
        this.price = price;
    }
    public Product(String name, Integer price) {
        super();
        this.name = name;
        this.price = price;
    }
    @Override
    public String toString() {
        return "Product [name=" + name + ", price=" + price + "]";
    }
    //重写clone的方法
    @Override
    public Product clone() {
        Product product = null;
        try {
            product = (Product)super.clone();
        } catch (CloneNotSupportedException e) {
            product = null;
            e.printStackTrace();
        }
        return product;
    }
}
package com.vince;

public class Test {
    public static void main(String[] args) {
        // TODO 对象的克隆
        Product product1 = new Product("篮球", 189);
        // 1.在Product实现CoCloneable接口
        // 2.重写clone方法
        Product product2 = product1.clone();
        System.out.println(product2);
        product2.setPrice(200);//篮球涨价了
        System.out.println(product1);//此时修改product2不会影响product1的值
        System.out.println(product2);
    }
}

深度克隆的使用

深度克隆的实现代码,例如:

package com.vince;
//实现Cloneable接口
public class Product implements Cloneable{
    private String name;
    private Integer price;
    public Shop shop;
    public Product(String name, Integer price, Shop shop) {
        this.name = name;
        this.price = price;
        this.shop = shop;
    }

    public Shop getShop() {
        return shop;
    } 

    public void setShop(Shop shop) {
        this.shop = shop;
    }

    public String getName() {
        return name;
    } 
    public void setName(String name) {
        this.name = name;
    }
    public Integer getPrice() {
        return price;
    }
    public void setPrice(Integer price) {
        this.price = price;
    }
    public Product(String name, Integer price) {
        super();
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "商店名:" + "\t" +name + "价格:" +"\t"+ price + "商店:" + shop;
    }
    //重写clone的方法
    @Override
    public Product clone() {
        Product product = null;
        try {
            // clone 的过程,new一个新的对象,将原对象中的属性完全复制(赋值)
            product = (Product)super.clone();
            // Product中的Shop实例克隆得到的对象
            shop = (Shop)product.getShop().clone();
            // 将新得到的克隆对象覆盖掉原来shop的属性值
            product.setShop(shop);
        } catch (CloneNotSupportedException e) {
            product = null;
            e.printStackTrace();
        }
        return product;
    }
}
package com.vince;

public class Shop implements Cloneable{
    private String name;
    private String address;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Shop(String name, String address) {
        super();
        this.name = name;
        this.address = address;
    }
    @Override
    public String toString() {
        return "Shop [name=" + name + ", address=" + address + "]";
    }

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

}

深度克隆的实现方式

深度克隆的第一种方式:如果被克隆对象中出现引用类型的变量(用户自定义变量),需要手动再次进行克隆。
缺点:如果类与类之间的关联关系较为复杂时,逐层实现克隆较为繁琐
深度克隆的第二种方式:如果被克隆对象中出现引用类型的变量(用户自定义变量),用序列化的方式实现克隆。序列化将在下一篇介绍。

总结

对象的克隆主要是为了解决在引用类型赋值时,通过引用类型赋值时修改属性值时所造成的修改后的数据不一致的问题;克隆分为浅克隆和深克隆,浅克隆只是适用于基本的数据类型,而对于非基本数据类型的任然不实用,同样修改时会存在破坏对象之间的独立性(如上述深克隆的使用中的例子,当Product中存在另外一个自定义类型Shop时,通过克隆后修改shop的属性任然会修改原来shop的属性值);深度克隆是把每一个对象都new一份到新的目标对象中,在要克隆的对象里面嵌套的非基本的数据类型和自定义对象都要进行克隆或者实现克隆的接口,当层次变多时实现起来就比较繁琐。还有最重要的一点是,所有的对象要想实现克隆,都必须要实现Cloneable方法和重写clone()方法。

附语
由于本人知识有限,若发现错误,希望大家能够批评和指正,谢谢

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
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对象克隆工具类的实现,我们可以方便地实现对象克隆操作,提高代码的可复用性和效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值