Java实现深克隆的两种方式

序列化和依次克隆各个可变的引用类型都可以实现深克隆,但是序列化的效率并不理想

下面是两种实现深克隆的实例,并且测试类对两种方法进行了对比:

1、重写clone方法使用父类中的clone()方法实现深克隆

package com.lk.B;

public class Worker implements Cloneable{
	private String name;
	private int age;
	public Worker(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		sb.append("姓名:"+name+",");
		sb.append("年龄:"+age+"
");
		return sb.toString();
	}
	@Override
	protected Worker clone() {
		// TODO Auto-generated method stub
		Worker worker = null;
		try {
			worker = (Worker) super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return worker;
	}
}

  2、重写clone()方法使用序列化方法实现深克隆

package com.lk.B;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Employee implements Cloneable,Serializable{
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	public Employee(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		sb.append("姓名:"+name+",");
		sb.append("年龄:"+age+"
");
		return sb.toString();
	}
	@Override
	protected Employee clone() {
		// TODO Auto-generated method stub
		Employee employss = null;
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(this);
			oos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
		try {
			ObjectInputStream ois = new ObjectInputStream(bais);
			employss = (Employee) ois.readObject();
			ois.close();
		} catch (IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return employss;
	}
}

  两者的实现方式在上面已经列出来了

下面编写了一个测试类来测试两种方式的效率

package com.lk.B;

import java.util.ArrayList;
import java.util.List;

public class Test3 {
	public static void main(String[] args) {
		List<Worker> workerList = new ArrayList<Worker>();//保存Worker对象
		List<Employee> employeelist = new ArrayList<Employee>();//保存Employee对象
		Worker worker = new Worker("阿坤", 21);
		Employee employee = new Employee("阿坤", 21);
		long time = System.currentTimeMillis();//取得系统当前时间
		//保存10000个Worker对象复制品到列表
		for(int i=0;i<10000;i++){
			workerList.add(worker.clone());
		}
		System.out.println("使用复制域的方式实现克隆所花费的时间:"+(System.currentTimeMillis()-time)+"ms");
		time = System.currentTimeMillis();//取得系统当前时间
		//保存10000个Employee对象复制品到列表
		for(int i=0;i<10000;i++){
			employeelist.add(employee.clone());
		}
		System.out.println("使用复制域的方式实现克隆所花费的时间:"+(System.currentTimeMillis()-time)+"ms");
	}
}

  运行结果:

/*
使用复制域的方式实现克隆所花费的时间:4ms
使用复制域的方式实现克隆所花费的时间:838ms
*/

  可以看出,可以使用序列化和逐个复制引用类型域的方式完成深克隆,其中序列化的方式效率很低。

原文地址:https://www.cnblogs.com/luankun0214/p/4398352.html