1
								         
						
				
				
						什么是
						Clone
						,容易实现吗?
				
		
		
				简单地说,
				Clone
				就是对于给定的一个对象实例
				o
				,得到另一个对象实例
				o’
				:
				o
				与
				o’
				类
		
		
				型相同(
				o.getClass() == o’.getClass()
				),内容相同(对于
				o/o’
				中的字段
				f
				,如果
				f
				是基本数据类型,则
				o.f == o’.f
				;如果
				f
				是对象引用,则
				o.f == o’.f
				或
				o.f
				指向的对象与
				o’.f
				指向的对象的内容相同)。通常称
				o’
				为
				o
				的克隆或副本。
		
		
				
						       
				
				直观上看,似乎很容易为一个类加上
				clone
				方法:
		
		
				
						
								| 
												class A {
										 
												
														       private Type1 field1;
										 
												
														    private Type2 field2;
										 
												
														     …..
										 
												
														    public Object clone() {
										 
												
														              A a = new A();
										 
												
														        a.field1 = a.getField1();
										 
												
														        a.field2 = a.getField2();
										 
												
														        ……
										 
												
														        return a;
										 
												
														    }
										 
												}
										 | 
				
		
		
				
						
						 
				
		
		
				然而,稍加推敲,就会发现这样的实现方法有两个问题:
		
		
				
						1.         
				
				要想某个类有
				clone
				功能,必须单独为其实现
				clone()
				函数,函数实现代码与该类定义密切相关。
		
		
				
						2.         
				
				即使基类
				A
				已有
				clone()
				函数,其子类
				ExtendA
				若要具备
				clone
				功能,则必须
				override
				其基类
				A
				的
				clone()
				函数。否则,对类型为
				ExtendA
				的对象
				ea
				的
				clone()
				方法的调用,会执行于类
				A
				中定义的
				clone()
				方法而返回一个类型为
				A
				的对象,它显然不是
				ea
				的克隆。
		
		
				
						
								2
								         
						
				
				
						Java
						对
						clone
						的支持
				
		
		
				万类之初的
				Object
				类有
				clone()
				方法:
		
		
				
						
								| 
												protected native Object clone() throws CloneNotSupportedException;
										 | 
				
		
		
				该方法是
				protected
				的,显然是留待被子类
				override
				的。该方法又是
				native
				的,必然做了
		
		
				与具体平台相关的底层工作。
		
		
				事实上,类
				Object
				的
				clone()
				方法首先会检查
				this.getClass()
				是否实现了
				Cloneable
				接口。
		
		
				Cloneable
				只是一个标志接口而已,用来标志该类是否有克隆功能。
		
		
				
						
								| 
												
														public
												
												
												
												
														interface
												
												
														Cloneable { 
												
														
														
												
										 
												}
										 | 
				
		
		
				
						       
				
				如果
				this.getClass()
				没有实现
				Cloneable
				接口,
				clone()
				就会抛
				CloneNotSupportedException
				返回。否则就会创建一个类型为
				this.getClass()
				的对象
				other
				,并将
				this
				各
				field
				的值赋值给
				other
				的对应
				field
				,然后返回
				other
				。
		
		
				
						       
				
				如此一来,我们要定义一个具有
				Clone
				功能的类就相当方便:
		
		
				
						1.         
				
				在类的声明中加入“
				implements Cloneable
				”,标志该类有克隆功能;
		
		
				
						2.         
				
				Override
				类
				Object
				的
				clone()
				方法,在该方法中调用
				super.clone()
				:
		
		
				
						
								| 
												class CloneableClass implements Cloneable {
										 
												
														       ……
										 
												public Object clone() {
										 
												
														       try {
										 
												
														       
														       return super.clone();
												//
												直接让
												Object.clone()
												为我们代劳一切
										 
												
														    } catch (CloneNotSupportedException e) {
										 
												
														       
														       throw new InternalError();
										 
												
														       }
										 
												}
										 
												}
										 | 
				
		
		
				
						 
				
		
		
				
						
								3
								         
						
				
				
						Shallow Clone
						与
						Deep Clone
				
		
		
				
						
								3.1
								    
						
				
				
						Shallow
				
				与
				
						Deep
				
				从何而来
				
						
						
				
		
		
				一个具有克隆功能的类,如果有可变(
				Mutable
				)类类型的字段
				field
				,如何为其克隆(副
		
		
				本)对象
				o’
				中的
				field
				赋值?
		
		
				
						       
				
				方法一、如
				Object
				的
				clone()
				方法所实现:设原始对象为
				o
				,其克隆对象是
				o’
				,执行
				o’.field = o.field
				。这样,
				o’.field
				与
				o.field
				指向同一个可变对象
				m
				。
				o
				与
				o’
				可能会相互影响(一个对象的状态可能会随着另一个对象的状态的改变而改变)。这样的
				Clone
				称为
				Shallow Clone
				。这也是
				Object
				的
				clone()
				方法的实现方式。
		
		
				
						       
				
				方法二、将
				o.field
				指向的可变对象
				m
				克隆,得到
				m’
				,将
				m’
				的引用赋值给
				o’.field
				。这样
				o’
				与
				o
				内容相同,且相互之间无影响(一个对象状态的改变不会影响另一个对象的状态)。这样的
				Clone
				称为
				Deep Clone
				。
		
		
				
						       Java Collection
				类库中具体数据结构类(
				ArrayList/LinkedList
				,
				HashSet/TreeSet
				,
				HashMap/TreeMap
				等)都具有克隆功能,且都是
				Shallow Clone
				,这样设计是合理的,因为它们不知道存放其中的每个数据对象是否也有克隆功能。
				System.arrayCopy()
				的实现采用的也是
				Shallow Clone
				。
		
		
				
						       Deep Clone
				对于实现不可变(
				Immutable
				)类很有帮助。设一个类包含可变类
				M
				类型的
				field
				,如何将其设计为不可变类呢?先为
				M
				实现
				Deep Clone
				功能,然后这样设计类
				ImmutableClass
				:
		
		
				
						
								| 
												class ImmutableClass {
										 
												
														       MutableClass m;
										 
												ImmutableClass(MutableClass m) {
										 
												
														       this.m = m.clone(); 
												//
												将传入的
												m
												的
												clone
												赋值给内部
												m
										 
												}
										 
												public MutableClass getM() {
										 
												
														    return this.m.clone(); 
												//
												将内部
												m
												的
												clone
												返回给外部
										 
												}
										 
												}
										 | 
				
		
		
				
						 
				
		
		
				
						       
				
		
		
				
						
								3.2
								    
						
				
				如何实现
				
						Deep Clone
				
		
		
				检查类有无可变类类型的字段。如果无,返回
				super.clone()
				即可;
		
		
				如果有,确保包含的可变类本身都实现了
				Deep Clone
				;
		
		
				Object o = super.clone(); 
				//
				先执行浅克隆,确保类型正确和基本类型及非可变类类型字段内容正确
				
						
						
				
		
		
				对于每一个可变类类型的字段
				field
				:
				
						
						
				
		
		
				
						       o.field = this.getField().clone();
		
		
				返回
				o
				。