java的对象克隆

来源:互联网 发布:ubuntu 邮件 编辑:程序博客网 时间:2024/06/07 11:12

对象的拷贝详解:推荐一片不错的博文:http://www.cnblogs.com/plokmju/p/7357205.html

首先需要明白,浅拷贝和深拷贝都是针对一个已有对象的操作。那先来看看浅拷贝和深拷贝的概念。

在 Java 中,除了基本数据类型(元类型)之外,还存在 类的实例对象 这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。

而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

所以到现在,就应该了解了,所谓的浅拷贝和深拷贝,只是在拷贝对象的时候,对 类的实例对象 这种引用数据类型的不同操作而已。

总结来说:

1、浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。

2、深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

既然已经了解了对 clone() 方法,只能对当前对象进行浅拷贝,引用类型依然是在传递引用。

那么,如何进行一个深拷贝呢?

比较常用的方案有两种:

1.实现Cloneable接口,重写clone()方法。
public class ObjClone1 implements Cloneable {
// 通过clone()实现拷贝
public String name;
public int age;
public ObjChild chd;
// 重写Object 的clone()
@Override
public Object clone() {
ObjClone1 objClone1;
try {
objClone1 = (ObjClone1) super.clone();
objClone1.chd = (ObjChild) this.chd.clone();
return objClone1;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
ObjClone1 objcA = new ObjClone1();
objcA.name = "pdj";
objcA.age = 18;
objcA.chd = new ObjChild();
objcA.chd.acct = "seniro";
objcA.chd.no = 123;

ObjClone1 objcB = (ObjClone1) objcA.clone();
System.out.println("objcA==objcB:" + (objcA == objcB));
System.out.println("objcA equals objcB:" + (objcA.equals(objcB)));
System.out.println(objcA.hashCode());
System.out.println(objcB.hashCode());
System.out.println(objcA.name);
System.out.println(objcB.name);
System.out.println(objcA.chd == objcB.chd);
System.out.println(objcA.chd.hashCode());
System.out.println(objcB.chd.hashCode());
}
}
class ObjChild implements Cloneable {
public String acct;
public int no;
@Override
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}

2.序列化方式。
public class ObjClone2 implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
public int age;
public static void main(String[] args) {
ObjClone2 objA = new ObjClone2();
ObjClone2 objC = new ObjClone2();
objA.name = "pdj";
objA.age = 18;
ObjClone2 objB = clone2(objA);
System.out.println(objA == objB);
System.out.println(objA == objC);
System.out.println("33" + objA.equals(objC));
System.out.println(objA.name);
System.out.println(objA.age);
System.out.println(objB.name);
System.out.println(objB.age);
System.out.println("=============================");
ObjClone2 objB2 = clone1(objA);
System.out.println(objA == objB2);
System.out.println(objA == objC);
System.out.println("33" + objA.equals(objC));
System.out.println(objA.name);
System.out.println(objA.age);
System.out.println(objB2.name);
System.out.println(objB2.age);
}
// 通过序列化方式,在内存中通过字节流的拷贝来实现把母对象写到一个字节流中,再从字节流中将其读出来,实现深度拷贝
public static <T extends Serializable> T clone1(T obj) {
// 拷贝产生的对象
T clonedObj = null;
try {
// 读取对象字节数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
// 分配内存空间,写入原始对象,生成新对象
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
// 返回新对象,并做类型转换
clonedObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return clonedObj;
}


// 通过apache.common.lang包中的SerializationUtils.clone()工具类实现深度序列化,简单方便
public static <T extends Serializable> T clone2(T obj) {
// 拷贝产生的对象
T clonedObj = null;
clonedObj = (T) SerializationUtils.clone(obj);
return clonedObj;
}


原创粉丝点击