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+"\n");
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+"\n");
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
*/
可以看出,可以使用序列化和逐个复制引用类型域的方式完成深克隆,其中序列化的方式效率很低。
Java实现深克隆的两种方式的更多相关文章
- 对Java代码加密的两种方式,防止反编译
使用Virbox Protector对Java项目加密有两种方式,一种是对War包加密,一种是对Jar包加密.Virbox Protector支持这两种文件格式加密,可以加密用于解析class文件的j ...
- Java新建线程的两种方式
Java新建线程有两种方式,一种是通过继承Thread类,一种是实现Runnable接口,下面是新建线程的两种方式. 我们假设有个竞赛,有一个选手A做俯卧撑,一个选手B做仰卧起坐.分别为两个线程: p ...
- Java实现多线程的两种方式
实现多线程的两种方式: 方式1: 继承Thread类 A: 自定义MyThread类继承Thread类 B: 在MyThread类中重写run() C: 创建MyThread类的对象 D: 启动线程对 ...
- [Java] HashMap遍历的两种方式
Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml第一种: Map map = new HashMap( ...
- java文件读写的两种方式
今天搞了下java文件的读写,自己也总结了一下,但是不全,只有两种方式,先直接看代码: public static void main(String[] args) throws IOExceptio ...
- K:java中序列化的两种方式—Serializable或Externalizable
在java中,对一个对象进行序列化操作,其有如下两种方式: 第一种: 通过实现java.io.Serializable接口,该接口是一个标志接口,其没有任何抽象方法需要进行重写,实现了Serializ ...
- java 实现websocket的两种方式
简单说明 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...
- java实现同步的两种方式
同步是多线程中的重要概念.同步的使用可以保证在多线程运行的环境中,程序不会产生设计之外的错误结果.同步的实现方式有两种,同步方法和同步块,这两种方式都要用到synchronized关键字. 给一个方法 ...
- Java线程创建的两种方式
java多线程总结一:线程的两种创建方式及优劣比较 (一)---之创建线程的两种方式 java实现多线程的两种方法的比较
随机推荐
- Xcode环境配置mysql
本文默认mysql安装目录为/usr/local/mysql 在项目的header search paths中添加/usr/local/mysql/includ 2.在项目的library searc ...
- django admin site (三)
1.自定义模板设置: ModelAdmin. add_form_template Path to a custom template, used by add_view(). ModelAdmin. ...
- HDU3033I love sneakers!(分组背包)
http://acm.hdu.edu.cn/showproblem.php?pid=3033 本题的意思就是说现在有n种牌子的鞋子,每种品牌有一些不同的鞋,每双鞋子都有一个特定的权值,现在要求每种品牌 ...
- android打电话、发短信实现
打电话: Intent intent = newIntent(Intent.ACTION_CALL,Uri.parse("tel:"+"156666666666" ...
- opencv直方图均衡化
#include <iostream> #include "highgui.h" #include "cv.h" #include "cx ...
- 用Log4Net记录NHibernate中执行的SQL语句及执行时间
首页,在web.config中加入以下配置: <configuration> <configSections> <section name="log4net&q ...
- Android与.Net交互模拟用户屏幕操作添加APN和网络4G/3G切换
前几天接到一个需求,我们的客户需要对手机网络接入点进行可用性测试,简单点说就是需要实现Android上的APN配置的添加,APN切换网络模式4G/3G/2G切换,我要调研下写个demo. 因为是要实现 ...
- 3.依赖倒置原则(Dependence Inversion Principle)
1.定义 高层模块不应该依赖于低层模块,二者都应该依赖于抽象:抽象不应该依赖细节:细节应该依赖抽象. 2.定义解读 依赖倒置原则在程序编码中经常运用,其核心思想就是面向接口编程,高层模块不应该依赖低层 ...
- ASP.net中GridView中增加一行记录并默认显示为编辑状态
//添加 protected void Button1_Click(object sender, EventArgs e) { DataSet ds = (DataSet)pa.GetDataSet( ...
- C++ Primer 学习笔记_46_STL实践与分析(20)--容器特有的算法
STL实践与分析 --容器特有的算法 与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必仅仅依赖于泛型操作.当中非常大的一个原因就是list容器不是依照内存中的顺序进 ...