1.Java对象复制概念
1.1 浅复制(浅克隆)
复制的对象的所有变量与含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
1.2 深复制(深度克隆)
复制的对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向复制的新对象,而不是原来的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
2.Java对象的clone()克隆方法
2.1 clone方法
clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足
- 对任何的对象x,都有x.clone() != x;也即克隆的对象与原对象不是同一个对象,他们有不同的内存地址
- 对任何的对象x,都有x.clone().getClass() == x.getClass(),也即克隆对象与原对象的类型一致。
- 如果对象x的equals()方法定义恰当,那么x.clone().equal(x)应该成立。
2.2 Java中对象的克隆
- 为了获取对象的一份拷贝,我们可以利用Object的clone()方法
- 在派生类中覆盖基类的clone()方法,并声明为public
- 在派生类的clone()方法中,调用super.clone()。
- 在派生类中实现Cloneable接口
2.3 示例
2.3.1 浅复制示例
package org.wem.im;
/**
*
* <p>
* Title: Person<br>
* Copyright: Copyright (c) 2016<br>
* Company: <br>
* </p>
*
* <p>
* Description: 测试Java对象浅克隆
* </p>
*
* @version v1.0.0
* @author kucs
* @date 2016年9月30日下午2:28:22
*
* Modification History:
*---------------------------------------------------------*
*
*/
public class Person implements Cloneable {
class Worker{
private String workName;
private String department;
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Worker [workName=" + workName + ", department=" + department + "]";
}
}
private String name;
private String age;
private String weight;
private String height;
private Worker worker;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public Worker getWorker() {
return worker;
}
public void setWorker(Worker worker) {
this.worker = worker;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
+ worker + "]";
}
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person();
Worker worker = p.new Worker();
worker.setWorkName("asiainfo");
worker.setDepartment("cboss");
p.setWorker(worker);
p.setName("kucs");
p.setAge("24");
p.setWeight("65");
p.setHeight("170");
Person p_clone = (Person) p.clone();
System.out.println("原对象信息:"+p.toString());
System.out.println("克隆对象信息:"+p_clone.toString());
//修改p_clone对象的值
p_clone.setName("kucs_clone");
//修改对象引用的对象的值
worker.setWorkName("asianinfo_clone");
System.out.println("修改后的克隆对象信息:"+p_clone.toString());
System.out.println("原对象信息:"+p.toString());
if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
System.out.println("浅复制对象,其引用的对象未复制");
}else{
System.out.println("非浅复制对象,其引用的对象也复制");
}
}
}
运行结果
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改后的克隆对象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
浅复制对象,其引用的对象未复制
结果说明:浅克隆之后的对象与原对象不是同一个对象。修改其中一个对象的值对另一个对象没有影响。
浅克隆中其引用的对象未复制,还是指向同一个对象。
2.3.2 深复制示例
对浅复制示例代码做了调整
package org.wem.im;
/**
*
* <p>
* Title: Person<br>
* Copyright: Copyright (c) 2016<br>
* Company: <br>
* </p>
*
* <p>
* Description: 测试Java对象深度克隆
* </p>
*
* @version v1.0.0
* @author kucs
* @date 2016年9月30日下午2:45:22
*
* Modification History:
*---------------------------------------------------------*
*
*/
public class Person implements Cloneable {
class Worker implements Cloneable{
private String workName;
private String department;
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "Worker [workName=" + workName + ", department=" + department + "]";
}
}
private String name;
private String age;
private String weight;
private String height;
private Worker worker;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public Worker getWorker() {
return worker;
}
public void setWorker(Worker worker) {
this.worker = worker;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
Person p = (Person) super.clone();
p.worker = (Worker) worker.clone();
return p;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
+ worker + "]";
}
public static void main(String[] args) throws CloneNotSupportedException {
Person p = new Person();
Worker worker = p.new Worker();
worker.setWorkName("asiainfo");
worker.setDepartment("cboss");
p.setWorker(worker);
p.setName("kucs");
p.setAge("24");
p.setWeight("65");
p.setHeight("170");
Person p_clone = (Person) p.clone();
System.out.println("原对象信息:"+p.toString());
System.out.println("克隆对象信息:"+p_clone.toString());
//修改p_clone对象的值
p_clone.setName("kucs_clone");
//修改对象引用的对象的值
worker.setWorkName("asianinfo_clone");
System.out.println("修改后的克隆对象信息:"+p_clone.toString());
System.out.println("原对象信息:"+p.toString());
if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
System.out.println("浅复制对象,其引用的对象未复制");
}else{
System.out.println("非浅复制对象,其引用的对象也复制");
}
}
}
运行结果:
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改后的克隆对象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
非浅复制对象,其引用的对象也复制
结果说明:深克隆中,对克隆后的对象修改值,不影响原对象的值。修改克隆后的对象引用的值,对原对象引用的对象也没有影响。
3.利用串行化来做深复制
这主要是为了避免重写比较复杂的深复制clone()方法。把对象写到流里的过程是串行化过程(Serialization),把对象从流中读取出来是并行化(Deserialization)过程。
注意:写在流里的对象时一个拷贝,而原对象仍然存在jvm中,因此串行化过程只是一个对象的拷贝。
在Java语言中,深复制一个对象,常常可以先使用对象实现Serializable接口,然后把对象写到一个流里,再从流里读取出来,便可以重建对象。
package org.wem.im;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
*
* <p>
* Title: Person<br>
* Copyright: Copyright (c) 2016<br>
* Company: <br>
* </p>
*
* <p>
* Description: 测试Java对象克隆
* </p>
*
* @version v1.0.0
* @author kucs
* @date 2016年9月30日下午2:28:22
*
* Modification History:
*---------------------------------------------------------*
*
*/
public class Person implements Serializable {
class Worker implements Serializable{
private String workName;
private String department;
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Worker [workName=" + workName + ", department=" + department + "]";
}
}
private String name;
private String age;
private String weight;
private String height;
private Worker worker;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public Worker getWorker() {
return worker;
}
public void setWorker(Worker worker) {
this.worker = worker;
}
public Object deepClone() throws IOException, 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();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + ", worker="
+ worker + "]";
}
public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
Person p = new Person();
Worker worker = p.new Worker();
worker.setWorkName("asiainfo");
worker.setDepartment("cboss");
p.setWorker(worker);
p.setName("kucs");
p.setAge("24");
p.setWeight("65");
p.setHeight("170");
Person p_clone = (Person) p.deepClone();
System.out.println("原对象信息:"+p.toString());
System.out.println("克隆对象信息:"+p_clone.toString());
//修改p_clone对象的值
p_clone.setName("kucs_clone");
//修改对象引用的对象的值
worker.setWorkName("asianinfo_clone");
System.out.println("修改后的克隆对象信息:"+p_clone.toString());
System.out.println("原对象信息:"+p.toString());
if(p.getWorker().getWorkName().equals(p_clone.getWorker().getWorkName())){
System.out.println("浅复制对象,其引用的对象未复制");
}else{
System.out.println("非浅复制对象,其引用的对象也复制");
}
}
}
运行结果
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
克隆对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
修改后的克隆对象信息:Person [name=kucs_clone, age=24, weight=65, height=170, worker=Worker [workName=asiainfo, department=cboss]]
原对象信息:Person [name=kucs, age=24, weight=65, height=170, worker=Worker [workName=asianinfo_clone, department=cboss]]
非浅复制对象,其引用的对象也复制
来源:oschina
链接:https://my.oschina.net/u/2808406/blog/753821