深拷贝(deep clone) 与 浅拷贝(shallow clone)
– 深复制 与 浅复制 概念
– 深复制(深克隆):被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。 那些引用引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象 。换而言之,
深复制把要复制的对象所引用的对象都复制了一遍。
– 浅复制(浅克隆):被复制对象的所有变量都含有与原来的对象 相同的值 ,而所有的对其他对象的引用 仍然指向原来的对象 。换而言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
java 的 clone() 方法 【定义在Object类中】
– clone 方法将对象复制了一份并返回给调用者。
一般而言,clone()方法 满足:
--1). 对任何的对象X, 都有x.clone()!= x
-- **克隆对象与原对象不是同一个对象**
--2). 对任何的对象X,都有 x.clone().getClass() == x.getClass()
-- 克隆对象与原对象的类型一样
--3). 如果对象X.equals() 方法定义恰当,那么x.clone().equals(x) 应该是成立。
java 中对象的克隆
– 1). 为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
– 2). 在派生类中覆盖基类的clone()方法,并声明为 public【 Object类中的** clone()方法为protected **的 】。
– 3). 在派生类的clone()方法中,调用super.clone()**.**
– 4). 在派生类中实现Cloneable接口。
说明:
–1). 为什么我们在派生类中覆盖Object的clone() 方法时,一定要调用super.clone() 呢?
在运行时刻,Object中的clone() 识别出你要复制的是哪一个对象,然后为此对象分配空间,
并进行对象的复制,将原对象的内容一一复制到新的对象的存储空间中。
–2). 继承自 java.lang.Object 类的clone() 方法是浅复制
现在存在一个问题,一个对象里存在另一个对象的引用,我们重写对象中的clone() 方法就能实现浅克隆或深克隆。
写一次代码就能搞定,假如一个对象中存在多个对象的引用该怎么处理。
这个问题我们这么解决 ?
利用序列化来做深复制 :
把对象写到流里的过程是序列化( **serialization** )过程,而把对象从流中读出来的过程则叫做反序列化( **Deserialization** )过程应当指出的是,写在流里的是对象的一个拷贝,而原对象任然存在于JVM里面。
在Java 语言里深复制一个对象,常常可以使对象实现Serialization 接口,然后把对象(实际上只是对象的一个深拷贝)写到一个流里,再从流里读出来,便可以重建对象。
– 这样做的前提是对象以及对象内部所有引用到的对象 都是可串行化** ( 串行化:就是可序列化的意思 ) 的,否则,就需要仔细考察那些不可串行化的对象可否设成 transient**,从而将之排除在复制过程之外。
注意: Cloneable 与 Serializable 都是marker Interface,也就是说他们只是一个标识接口,没有定义任何方法。
当一个类实现了Serializable 接口时,表明该类可被序列化,这个时候Eclipse会要求你为该类定义一个字段,
该字段名字为 serial Version UID, 类型为long, 提示信息如下
你可以随便写一个,在Eclipse中它替你生成一个,有两种方式:
--1). 一个是默认的1L , 比如: private static final long serialVersionUID = 1L;
--2). 一个是很据类名、接口名、成员方法及属性等来生成一个64位的哈希字段, 比如:
private static final long serialVersionUID = 8940196742313994740L; 之类的。
如果你没有考虑到兼容性问题时,就把它关掉,不过有这个功能是好的,只要任何类别实现了Serializable这个接口的话,如果没有加入serialVersionUID,eclipse都会给你warning提示,这个serialVersionUID为了让该类别Serializable 向后兼容 。
什么是** 向后兼容性?**
—- 如果你的对象序列化后存到硬盘上面后,可是后来你却更改了类的field(增加或减少或改名),
当你反序列化时,就会出现Exception,这样会造成不兼容性的问题
—- 但当serialVersionUID 相同时,它就会将不一样的field以type的缺省值Deserialize,
这个可以避开不兼容性的问题