目录
对象的克隆
克隆的做用
克隆的分类
克隆的使用
浅克隆的使用
深度克隆的使用
深度克隆的实现方式
总结java
java当中的克隆跟生物上所说的克隆相似,就是复制出一个如出一辙的个体,固然迁移到java当中,那就是复制出一个如出一辙对象,别忘了java当中有句话叫作一切皆对象。经过克隆就能提升对象的独立性,使用起来更加方便,也更安全。安全
对象克隆主要是为了解决引用类型在进行等号赋值时使得两个引用同时指向同一个对象实例,从而致使经过两个引用去操做对象时,会直接更改实例中的属性破坏对象的相互独立性。ide
//例如一下代码段 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); }
上述代码运行的结果如图:
this
由上述运行结果可知,在引用类型当中,因为都是指向同一个对象实例,当咱们用引用类型去修改对象实例的值时,原来对象的属性也会跟着改变,从而致使了数据的不一致性。对象的克隆就能解决上述问题,防止发生此类状况。spa
浅克隆以下图所示,只适用于基本的数据类型,对于值传递就只是赋值,把全部属性都拿过来赋值给当前对象。当要克隆的对象里面存在另一个非基本数据类型的对象实例时,因为只是简单地经过等号赋值,又至关于指向的是同一个实例对象,在进行修改时一样会修改原来的属性。
3d
而深度克隆就是把对象的全部属性都通通复制一份新的到目标对象里面去,使他成为一个独立的对象,当修改新的对象实例的属性时,原来对象中的属性任然不变。
code
浅克隆的实现代码,例如:对象
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); } }
深度克隆的实现代码,例如:blog
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()方法。
附语 因为本人知识有限,若发现错误,但愿你们可以批评和指正,谢谢