package com.pachira.c;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/*
* Java的浅拷贝和深拷贝
* 【浅拷贝】:重写Object的clone()方法且实现Cloneable这个空接口(规则如下):
* +---------------------------------------------------------------------------------------------+
* | 基本类型 | 拷贝其值,比如int、float等。 |
* +---------------------------------------------------------------------------------------------+
* | String | 拷贝其地址引用,但在修改时,它从字符串池中重新生成一个新字符串,原有字符串对象保持不变。 |
* +---------------------------------------------------------------------------------------------+
* | 对象 | 拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。 |
* +---------------------------------------------------------------------------------------------+
*
* 【深拷贝】:利用序列化实现对象的拷贝:
* 原理:把母对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。
* 注意:被克隆的对象需要实现Serializable接口
*
* 参考:
* http://cmsblogs.com/?p=58
* http://www.cnblogs.com/chenssy/p/3308489.html
*/
public class LClone implements Cloneable, Serializable{
private static final long serialVersionUID = -1991475817161553683L;
private int id;
private String name;
private Email email;
public LClone() {
}
public LClone(int id, String name, Email email) {
this.id = id;
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
public LClone clone() throws CloneNotSupportedException {
return (LClone)super.clone();
}
@Override
public String toString() {
return "id: " + this.id + ", name: " + this.name + ", email: " + this.email;
}
public static void main(String[] args) throws CloneNotSupportedException {
Email email = new LClone.Email("welcome.");
LClone stu = new LClone(2, "Tom", email);
LClone stu2 = stu.clone();
stu2.setId(3);
stu2.setName("Jim");
System.out.println(stu);
System.out.println(stu2);
System.out.println(stu.getEmail() == stu2.getEmail());
CloneUtil cloneUtil = new LClone.CloneUtil();
LClone stu3 = cloneUtil.clone(stu);
System.out.println(stu.getEmail() == stu3.getEmail());
// id: 2, name: Tom, email: welcome.
// id: 3, name: Jim, email: welcome.
// true
// false
}
static class Email implements Serializable{
private static final long serialVersionUID = 717077025366523218L;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Email(String content) {
this.content = content;
}
@Override
public String toString() {
return this.content;
}
}
static class CloneUtil {
@SuppressWarnings("unchecked")
public <T extends Serializable> T clone(T obj){
T newT = null;
try {
//写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
//分配内存,写入原始对象,生成新对象
ByteArrayInputStream bais = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
//返回生成的新对象
newT = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return newT;
}
}
}