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

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

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

  1. package com.lk.B;
  2.  
  3. public class Worker implements Cloneable{
  4. private String name;
  5. private int age;
  6. public Worker(String name,int age){
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. // TODO Auto-generated method stub
  25. StringBuffer sb = new StringBuffer();
  26. sb.append("姓名:"+name+",");
  27. sb.append("年龄:"+age+"\n");
  28. return sb.toString();
  29. }
  30. @Override
  31. protected Worker clone() {
  32. // TODO Auto-generated method stub
  33. Worker worker = null;
  34. try {
  35. worker = (Worker) super.clone();
  36. } catch (CloneNotSupportedException e) {
  37. // TODO Auto-generated catch block
  38. e.printStackTrace();
  39. }
  40. return worker;
  41. }
  42. }

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

  1. package com.lk.B;
  2.  
  3. import java.io.ByteArrayInputStream;
  4. import java.io.ByteArrayOutputStream;
  5. import java.io.IOException;
  6. import java.io.ObjectInputStream;
  7. import java.io.ObjectOutputStream;
  8. import java.io.Serializable;
  9.  
  10. public class Employee implements Cloneable,Serializable{
  11. private static final long serialVersionUID = 1L;
  12. private String name;
  13. private int age;
  14. public Employee(String name,int age){
  15. this.name = name;
  16. this.age = age;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public int getAge() {
  25. return age;
  26. }
  27. public void setAge(int age) {
  28. this.age = age;
  29. }
  30. @Override
  31. public String toString() {
  32. // TODO Auto-generated method stub
  33. StringBuffer sb = new StringBuffer();
  34. sb.append("姓名:"+name+",");
  35. sb.append("年龄:"+age+"\n");
  36. return sb.toString();
  37. }
  38. @Override
  39. protected Employee clone() {
  40. // TODO Auto-generated method stub
  41. Employee employss = null;
  42.  
  43. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  44. try {
  45. ObjectOutputStream oos = new ObjectOutputStream(baos);
  46. oos.writeObject(this);
  47. oos.close();
  48. } catch (IOException e) {
  49. // TODO Auto-generated catch block
  50. e.printStackTrace();
  51. }
  52.  
  53. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  54. try {
  55. ObjectInputStream ois = new ObjectInputStream(bais);
  56. employss = (Employee) ois.readObject();
  57. ois.close();
  58. } catch (IOException | ClassNotFoundException e) {
  59. // TODO Auto-generated catch block
  60. e.printStackTrace();
  61. }
  62. return employss;
  63. }
  64. }

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

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

  1. package com.lk.B;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. public class Test3 {
  7. public static void main(String[] args) {
  8. List<Worker> workerList = new ArrayList<Worker>();//保存Worker对象
  9. List<Employee> employeelist = new ArrayList<Employee>();//保存Employee对象
  10. Worker worker = new Worker("阿坤", 21);
  11. Employee employee = new Employee("阿坤", 21);
  12. long time = System.currentTimeMillis();//取得系统当前时间
  13. //保存10000个Worker对象复制品到列表
  14. for(int i=0;i<10000;i++){
  15. workerList.add(worker.clone());
  16. }
  17. System.out.println("使用复制域的方式实现克隆所花费的时间:"+(System.currentTimeMillis()-time)+"ms");
  18. time = System.currentTimeMillis();//取得系统当前时间
  19. //保存10000个Employee对象复制品到列表
  20. for(int i=0;i<10000;i++){
  21. employeelist.add(employee.clone());
  22. }
  23. System.out.println("使用复制域的方式实现克隆所花费的时间:"+(System.currentTimeMillis()-time)+"ms");
  24. }
  25. }

  运行结果:

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

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

Java实现深克隆的两种方式的更多相关文章

  1. 对Java代码加密的两种方式,防止反编译

    使用Virbox Protector对Java项目加密有两种方式,一种是对War包加密,一种是对Jar包加密.Virbox Protector支持这两种文件格式加密,可以加密用于解析class文件的j ...

  2. Java新建线程的两种方式

    Java新建线程有两种方式,一种是通过继承Thread类,一种是实现Runnable接口,下面是新建线程的两种方式. 我们假设有个竞赛,有一个选手A做俯卧撑,一个选手B做仰卧起坐.分别为两个线程: p ...

  3. Java实现多线程的两种方式

    实现多线程的两种方式: 方式1: 继承Thread类 A: 自定义MyThread类继承Thread类 B: 在MyThread类中重写run() C: 创建MyThread类的对象 D: 启动线程对 ...

  4. [Java] HashMap遍历的两种方式

    Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml第一种: Map map = new HashMap( ...

  5. java文件读写的两种方式

    今天搞了下java文件的读写,自己也总结了一下,但是不全,只有两种方式,先直接看代码: public static void main(String[] args) throws IOExceptio ...

  6. K:java中序列化的两种方式—Serializable或Externalizable

    在java中,对一个对象进行序列化操作,其有如下两种方式: 第一种: 通过实现java.io.Serializable接口,该接口是一个标志接口,其没有任何抽象方法需要进行重写,实现了Serializ ...

  7. java 实现websocket的两种方式

    简单说明 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...

  8. java实现同步的两种方式

    同步是多线程中的重要概念.同步的使用可以保证在多线程运行的环境中,程序不会产生设计之外的错误结果.同步的实现方式有两种,同步方法和同步块,这两种方式都要用到synchronized关键字. 给一个方法 ...

  9. Java线程创建的两种方式

    java多线程总结一:线程的两种创建方式及优劣比较 (一)---之创建线程的两种方式 java实现多线程的两种方法的比较

随机推荐

  1. POJ3321 Apple Tree (树状数组)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16180   Accepted: 4836 Descr ...

  2. Spring REST实践之REST基本介绍

    REST是什么 REST(REpresentational State Transfer)是一个设计分布式web应用的框架风格,有六个基本原则: Client-Server:应用的参独立与者可分为Cl ...

  3. python 缩进问题

    200 ? "200px" : this.width)!important;} --> 介绍 在python中认为规定4个空格缩进,缩进的代码可以理解成一个块,但是使用缩进也 ...

  4. How to log in to Amazon EC2 using PEM format from SecureCRT

    SecureCRT requires both a private and a public key. Use the supplied key.pem file from EC2 here as y ...

  5. C#完成超酷的图像效果 (附demo)

    如果您觉得C#制作的艺术字比较好玩, 但是还觉得没看够,不过瘾,那么我今天就让您一饱眼福, 看看C#如何制作的效果超酷的图像. (注: 我之前曾写过类似的文章, 但没有原理说明, 代码注释不够详细, ...

  6. Flexigrid在IE下不显示数据的处理

    文章总结自我的论坛提问: http://bbs.csdn.net/topics/390498434?page=1#post-394918028 解决方法: 网上的答案经我验证都是不靠谱的,以后大家就知 ...

  7. JavaScript创建Map对象(转)

    JavaScript 里面本身没有map对象,用JavaScript的Array来实现Map的数据结构. /* * MAP对象,实现MAP功能 * * 接口: * size()     获取MAP元素 ...

  8. ueditor 编辑器再thinkphp中使用 解决转义问题

    在前台common.php文件中加入下面的函数就可以解决了 <?php //取消thinkphp里面的转义 if (get_magic_quotes_gpc()) { function stri ...

  9. 【转】Delphi多线程学习(9):多线程数据库查询(ADO)

    原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...

  10. 微信公共服务平台开发(.Net 的实现)9-------处理二维码

    今天我们来共同学习一下微信公共服务平台中一个重要内容---二维码扫描.众所周知二维码目前应用范围很广,在这里不再叙述背景了,但是值得一提的是目前大家手机上面应用的二维码扫描工具是支持的都是QR码和PD ...