浅克隆和深克隆的区别
2018-08-21 05:33:06来源:博客园 阅读 ()
在Java中对象的克隆有深克隆和浅克隆之分。有这种区分的原因是Java中分为基本数据类型和引用数据类型,对于不同的数据类型在内存中的存储的区域是不同的。基本数据类型存储在栈中,引用数据类型存储在堆中。
什么是克隆
克隆就是依据已经有的数据,创造一份新的完全一样的数据拷贝。
浅克隆
实现克隆有多种方式,可以手工的new出一个新的对象,然后将原来的对象信息一个一个的set到新的对象中。还有就是使用clone方法。使用clone方法必须满足:
1、要实现浅克隆被克隆的类必须实现Cloneable接口
2、未实现接口会跑出CloneNotSupportedException异常
示例
package com.winter.clone;
public class Customer implements Cloneable { public int ID; public int age; public Address address;
public int getID() { return ID; } public void setID(int iD) { ID = iD; } 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; }
public Customer(int iD, int age, Address address) { super(); ID = iD; this.age = age; this.address = address; }
@Override public String toString() { return "Customer [ID=" + ID + ", age=" + age + ", address=" + address + "]"; }
@Override public Customer clone() throws CloneNotSupportedException { return (Customer) super.clone(); }
public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("CH", "SD", "QD"); Customer customer1 = new Customer(1, 23, address); Customer customer2 = customer1.clone(); customer2.getAddress().setCity("JN"); customer2.setID(2); System.out.println("改变customer2 id:2与address:JN"); System.out.println("customer1:" + customer1.toString()); System.out.println("customer2:" + customer2.toString()); } }
class Address { private String country; private String province; private String city;
public String getCountry() { return country; }
public void setCountry(String country) { this.country = country; }
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 [country=" + country + ", province=" + province + ", city=" + city + "]"; }
public Address(String country, String province, String city) { super(); this.country = country; this.province = province; this.city = city; } } |
改变customer2 id:2与address:JN customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=JN]] customer2:Customer [ID=2, age=23, address=Address [country=CH, province=SD, city=JN]] |
上面分析得到,clone后新旧对象互不影响,customer2修改了id后没有影响到customer1,但是修改了customer2的address属性的city值为JN后,发现customer1的address值也发生了改变。这样就没有达到完全复制、相互之间完全没有影响的目的。这样就需要进行深克隆。
深克隆
定义:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。深克隆的是实现实际上是对对象的序列化和反序列化。
深克隆的实现就是在引用类型所在的类实现Cloneable接口,并使用public访问修饰符重写clone方法。
示例一:
1.Address类实现Cloneable接口,重写clone方法;
@Override public Address clone() throws CloneNotSupportedException { return (Address) super.clone(); } |
- 在Customer类的clone方法中调用Address类的clone方法。
@Override public Customer clone() throws CloneNotSupportedException { Customer customer = (Customer) super.clone(); customer.address = address.clone(); return customer; } |
发现customer2无论如何修改,customer1都没有受到影响。
改变customer2 id:2与address:JN customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=QD]] customer2:Customer [ID=2, age=23, address=Address [country=CH, province=SD, city=JN]] |
实现深克隆的另一种方法就是使用序列化,将对象写入到流中,这样对象的内容就变成了字节流,也就不存在什么引用了。然后读取字节流反序列化为对象就完成了完全的复制操作了。
1、被克隆类以及被克隆类的引用必须实现Serializable接口
2、未实现接口会抛出NotSerializableException异常
示例二:
public static Object cloneObject(Object obj) throws IOException, ClassNotFoundException{ ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(obj); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in =new ObjectInputStream(byteIn); return in.readObject(); } |
改变customer2 id:2与address:JN customer1:Customer [ID=1, age=23, address=Address [country=CH, province=SD, city=QD]] customer2:Customer [ID=2, age=23, address=Address [country=CH, province=SD, city=JN]] |
总结
1.浅克隆:只复制基本类型的数据,引用类型的数据只复制了引用的地址,引用的对象并没有复制,在新的对象中修改引用类型的数据会影响原对象中的引用。
2.深克隆:是在引用类型的类中也实现了clone,是clone的嵌套,复制后的对象与原对象之间完全不会影响。
3.使用序列化也能完成深复制的功能:对象序列化后写入流中,此时也就不存在引用什么的概念了,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash