java Clone
2013-09-26 11:13
441 查看
一、 浅复制与深复制概念
1)
浅复制:原对象和克隆后的对象的属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是同一个引用。
2)
深复制:原对象和克隆后的对象的成员属性中属性类型是基本数据类型和String的成员属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是则是不同的引用,即克隆后的属性对象会指向堆中新的对象。
二、 总结
1)
浅复制的类只需要实现Cloneable接口实现。
2)
深度复制的类中成员属性如果有自定义的引用数据类型时,那么自定义的类也需要实现Cloneable接口才行。
3)
深度复制时如果类的成员属性是List、Map时,仅仅实现Cloneable接口这些成员属性是做不到深度复制的,如果要实现深度复制则需要重新new。
4)
通过序列化实现的深度复制是真正的深度复制,所有的引用对象都会是重新new出来的拷贝,不会影响原对象。
三、 代码案例
1) 浅复制:
package clone.easy;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher {
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
package clone.easy;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*
浅复制(浅克隆)
*
被复制对象的所有变量都含有与原来的对象相同的值,
*
而所有的对其他对象的引用仍然指向原来的对象。
*
换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
*@author13061494
*
*/
publicclass Student
implements Cloneable {
private String
name;
privateintage;
private List<String>
list =
new ArrayList<String>();
private Teacher
teacher;
public Object clone() {
System.out.println("clone");
Object o = null;
try {
o = (Student)
super.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
return o;
}
publicstaticvoid main(String[] args)
throws Exception {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
student.name =
"gx";
student.age = 15;
student.list.add("list");
Student
clone = (Student) student.clone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone
clone.easy.Student@6d8e6d8e[
name=cm
age=15
list=[list, clone list]
teacher=clone.easy.Teacher@35fd35fd[
name=clone Teacher
age=20
]
]
clone.easy.Student@33533353[
name=gx
age=15
list=[list, clone list]
teacher=clone.easy.Teacher@35fd35fd[
name=clone Teacher
age=20
]
]
2) 深度复制
package clone.deep;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher
implements Cloneable{
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
protected Object clone()
throws CloneNotSupportedException {
//
TODO Auto-generated method stub
returnsuper.clone();
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.<
15e4e
em>MULTI_LINE_STYLE);
}
}
package clone.deep;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*深复制(深克隆)
*被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。
*那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
*换言之,深复制把要复制的对象所引用的对象都复制了一遍
*@author13061494
*
*/
publicclass Student
implements Cloneable {
private String
name;
privateintage;
private Teacher
teacher;
private List<String>
list;
private List<String>
newList =
new ArrayList<String>();
private Map<String, String>
map =
new HashMap<String, String>();
public Object clone()
throws CloneNotSupportedException{
System.out.println("clone");
Student o = null;
o = (Student) super.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
o.teacher = (Teacher)teacher.clone();
return o;
}
publicstaticvoid main(String[] args)
throws CloneNotSupportedException {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
student.name =
"gx";
student.age = 15;
List<String> list =
new ArrayList<String>();
list.add("list");
student.list = list;
student.newList.add("newList");
student.map.put("map",
"map");
Student clone = (Student) student.clone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
clone.newList.add("clone newList");
clone.map.put("clone map",
"clone map");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone
clone.deep.Student@6e4c6e4c[
name=cm
age=15
teacher=clone.deep.Teacher@6e566e56[
name=clone Teacher
age=20
]
list=[list, clone list]
newList=[newList, clone newList]
map={clone map=clone map, map=map}
]
clone.deep.Student@336a336a[
name=gx
age=15
teacher=clone.deep.Teacher@364d364d[
name=teacher
age=20
]
list=[list, clone list]
newList=[newList, clone newList]
map={clone map=clone map, map=map}
]
3) 串行化来做深复制
package clone.deep.serialize;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher
implements Serializable{
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid
setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
package clone.deep.serialize;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*利用串行化来做深复制
*把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;
*而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。
*应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
*在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
*@author13061494
*
*/
publicclass Student
implements Serializable {
private String
name;
privateintage;
private List<String>
list;
private Map<String, String>
map;
private Teacher
teacher;
public Object deepClone()
throws IOException, OptionalDataException, ClassNotFoundException {//
将对象写到流里
ByteArrayOutputStream bo =
new ByteArrayOutputStream();
ObjectOutputStream oo =
new ObjectOutputStream(bo);
oo.writeObject(this);//
从流里读出来
ByteArrayInputStream bi =
new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi =
new ObjectInputStream(bi);
return (oi.readObject());
}
publicstaticvoid main(String[] args)
throws Exception {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
List<String> list =
new ArrayList<String>();
list.add("list");
student.list = list;
student.map =
new HashMap<String, String>();
student.map.put("map",
"map");
student.name =
"gx";
student.age = 15;
Student clone = (Student) student.deepClone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
clone.map.put("clone map",
"clone map");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone.deep.serialize.Student@3adb3adb[
name=cm
age=15
list=[list, clone list]
map={clone map=clone map, map=map}
teacher=clone.deep.serialize.Teacher@5e0f5e0f[
name=clone Teacher
age=20
]
]
clone.deep.serialize.Student@34003400[
name=gx
age=15
list=[list]
map={map=map}
teacher=clone.deep.serialize.Teacher@36b736b7[
name=teacher
age=20
]
]
1)
浅复制:原对象和克隆后的对象的属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是同一个引用。
2)
深复制:原对象和克隆后的对象的成员属性中属性类型是基本数据类型和String的成员属性值是一样的,原对象的属性对象和克隆后的属性对象指向的是则是不同的引用,即克隆后的属性对象会指向堆中新的对象。
二、 总结
1)
浅复制的类只需要实现Cloneable接口实现。
2)
深度复制的类中成员属性如果有自定义的引用数据类型时,那么自定义的类也需要实现Cloneable接口才行。
3)
深度复制时如果类的成员属性是List、Map时,仅仅实现Cloneable接口这些成员属性是做不到深度复制的,如果要实现深度复制则需要重新new。
4)
通过序列化实现的深度复制是真正的深度复制,所有的引用对象都会是重新new出来的拷贝,不会影响原对象。
三、 代码案例
1) 浅复制:
package clone.easy;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher {
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
package clone.easy;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*
浅复制(浅克隆)
*
被复制对象的所有变量都含有与原来的对象相同的值,
*
而所有的对其他对象的引用仍然指向原来的对象。
*
换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
*@author13061494
*
*/
publicclass Student
implements Cloneable {
private String
name;
privateintage;
private List<String>
list =
new ArrayList<String>();
private Teacher
teacher;
public Object clone() {
System.out.println("clone");
Object o = null;
try {
o = (Student)
super.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
return o;
}
publicstaticvoid main(String[] args)
throws Exception {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
student.name =
"gx";
student.age = 15;
student.list.add("list");
Student
clone = (Student) student.clone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone
clone.easy.Student@6d8e6d8e[
name=cm
age=15
list=[list, clone list]
teacher=clone.easy.Teacher@35fd35fd[
name=clone Teacher
age=20
]
]
clone.easy.Student@33533353[
name=gx
age=15
list=[list, clone list]
teacher=clone.easy.Teacher@35fd35fd[
name=clone Teacher
age=20
]
]
2) 深度复制
package clone.deep;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher
implements Cloneable{
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
protected Object clone()
throws CloneNotSupportedException {
//
TODO Auto-generated method stub
returnsuper.clone();
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.<
15e4e
em>MULTI_LINE_STYLE);
}
}
package clone.deep;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*深复制(深克隆)
*被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。
*那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
*换言之,深复制把要复制的对象所引用的对象都复制了一遍
*@author13061494
*
*/
publicclass Student
implements Cloneable {
private String
name;
privateintage;
private Teacher
teacher;
private List<String>
list;
private List<String>
newList =
new ArrayList<String>();
private Map<String, String>
map =
new HashMap<String, String>();
public Object clone()
throws CloneNotSupportedException{
System.out.println("clone");
Student o = null;
o = (Student) super.clone();// Object
中的clone()识别出你要复制的是哪一个对象。
o.teacher = (Teacher)teacher.clone();
return o;
}
publicstaticvoid main(String[] args)
throws CloneNotSupportedException {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
student.name =
"gx";
student.age = 15;
List<String> list =
new ArrayList<String>();
list.add("list");
student.list = list;
student.newList.add("newList");
student.map.put("map",
"map");
Student clone = (Student) student.clone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
clone.newList.add("clone newList");
clone.map.put("clone map",
"clone map");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone
clone.deep.Student@6e4c6e4c[
name=cm
age=15
teacher=clone.deep.Teacher@6e566e56[
name=clone Teacher
age=20
]
list=[list, clone list]
newList=[newList, clone newList]
map={clone map=clone map, map=map}
]
clone.deep.Student@336a336a[
name=gx
age=15
teacher=clone.deep.Teacher@364d364d[
name=teacher
age=20
]
list=[list, clone list]
newList=[newList, clone newList]
map={clone map=clone map, map=map}
]
3) 串行化来做深复制
package clone.deep.serialize;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
publicclass Teacher
implements Serializable{
private String
name;
privateintage;
public String getName() {
returnname;
}
publicvoid
setName(String name) {
this.name = name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int
age) {
this.age = age;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
package clone.deep.serialize;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
*利用串行化来做深复制
*把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;
*而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。
*应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
*在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
*@author13061494
*
*/
publicclass Student
implements Serializable {
private String
name;
privateintage;
private List<String>
list;
private Map<String, String>
map;
private Teacher
teacher;
public Object deepClone()
throws IOException, OptionalDataException, ClassNotFoundException {//
将对象写到流里
ByteArrayOutputStream bo =
new ByteArrayOutputStream();
ObjectOutputStream oo =
new ObjectOutputStream(bo);
oo.writeObject(this);//
从流里读出来
ByteArrayInputStream bi =
new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi =
new ObjectInputStream(bi);
return (oi.readObject());
}
publicstaticvoid main(String[] args)
throws Exception {
Student student =
new Student();
Teacher teacher =
new Teacher();
teacher.setName("teacher");
teacher.setAge(20);
student.teacher = teacher;
List<String> list =
new ArrayList<String>();
list.add("list");
student.list = list;
student.map =
new HashMap<String, String>();
student.map.put("map",
"map");
student.name =
"gx";
student.age = 15;
Student clone = (Student) student.deepClone();
clone.name =
"cm";
clone.teacher.setName("clone Teacher");
clone.list.add("clone list");
clone.map.put("clone map",
"clone map");
System.out.println(clone);
System.out.println(student);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
运行结果:
clone.deep.serialize.Student@3adb3adb[
name=cm
age=15
list=[list, clone list]
map={clone map=clone map, map=map}
teacher=clone.deep.serialize.Teacher@5e0f5e0f[
name=clone Teacher
age=20
]
]
clone.deep.serialize.Student@34003400[
name=gx
age=15
list=[list]
map={map=map}
teacher=clone.deep.serialize.Teacher@36b736b7[
name=teacher
age=20
]
]
相关文章推荐
- java中的clone
- Java中Cloneable接口
- Java基础[6]-2-对象克隆(Cloneable)
- java对象克隆clone
- 详解Java中clone的写法
- java中创建对象的几种方法和clone
- Java-Clone改写
- 关于java clone的一个例子
- java -- 禁止对象clone
- Java的clone方法
- java-基础-Clone()
- 转 java中引用及对象的clone
- java 对象clone
- Java克隆(Clone)的应用
- JAVA clone的简单理解
- Java中的clone
- 详解Java中的clone方法
- java的Cloneable、Serializable接口
- Java中的Cloneable(未完待续)
- Java| Java对象克隆Clone(1)