Java深入学习26:Java深度克隆

深克隆和浅克隆区别

浅克隆: 只copy对象引用,不copy对象本身。即对象地址不变,仍然只存在一个对象。

深克隆: 不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

深克隆的两个方案

方案1——实现Cloneable接口,重写Object类地 clone()方法

分如下三步

1. 对象的类实现Cloneable接口(必须,否则会抛出CloneNotSupportedException异常);

2. 覆盖Object类的clone()方法 (覆盖clone()方法,将访问修饰符改为public,默认是protected);

3. 在clone()方法中调用super.clone();

public classCloneTest {public static void main(String[] args) throwsCloneNotSupportedException {

Student stu= new Student("A");

Student deep= stu.clone();//深克隆

Student shallow = stu;//浅克隆

shallow.setName("B");

System.out.println("original: " + stu);//Student{name='B'}

System.out.println("deep: " + deep);//Student{name='A'}

System.out.println("shallow: " + shallow);//Student{name='B'}

}

}class Student implementsCloneable{privateString name;publicStudent(String name) {this.name =name;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}

@Overridepublic Student clone() throws CloneNotSupportedException {

return (Student) super.clone();

}

@OverridepublicString toString() {return "Student{" +

"name='" + name + '\'' +

'}';

}

}

深克隆的多级深克隆问题:

重写clone()方法,只会深克隆类和类中所有非基本数据类型的属性对应的类。对于类中的属性对应的类,是无法深克隆的,如果深克隆类中的属性对应的类,需要额外的调用类中的属性对应的类clone方法

public classCloneTest {public static void main(String[] args) throwsCloneNotSupportedException {

School sch= new School("a",new Student("A"));

School deepSch= sch.clone();//深克隆

School shallowSch = sch;//浅克隆

shallowSch.getStu().setName("B");

System.out.println(sch);//School{name='a', stu=Student{name='B'}}

System.out.println(deepSch);//School{name='a', stu=Student{name='A'}}

System.out.println(shallowSch);//School{name='a', stu=Student{name='B'}}

}

}class School implementsCloneable{privateString name;privateStudent stu;

@Overridepublic School clone() throwsCloneNotSupportedException {//return (School)super.clone();//该方法无法深克隆Sch中的Student

School clone = (School) super.clone();

clone.setStu(this.stu.clone());returnclone;

}publicSchool(String name, Student stu) {this.name =name;this.stu =stu;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicStudent getStu() {returnstu;

}public voidsetStu(Student stu) {this.stu =stu;

}

@OverridepublicString toString() {return "School{" +

"name='" + name + '\'' +

", stu=" + stu +

'}';

}

}

方案2——序列化深克隆

什么是序列化?

1- java序列化是指把java对象转换为字节序列的过程,而java反序列化是指把字节序列恢复为java对象的过程

2- 序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存的java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

3- 反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

4- 序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态

import java.io.*;public classSerializeDeepCloneTest {public static voidmain(String[] args) {

SchoolSeri sch= new SchoolSeri("zjut",new StudentSeri("tyj"));

SchoolSeri schSeri= null;

System.out.println(sch);try{

schSeri=SerializeDeepCloneUtil.deepClone(sch);

System.out.println(sch);

}catch(Exception e) {

e.printStackTrace();

}

System.out.println(sch==schSeri);

}

}classSerializeDeepCloneUtil{//序列化深克隆

static T deepClone(T obj){if(obj ==null){return null;

}

T cloneObj= null;//序列化

ByteArrayOutputStream bout = null;

ObjectOutputStream oos= null;try{//创建字节数组输出流//new ByteArrayOutputStream() Creates a new byte array output stream.

bout = newByteArrayOutputStream();//创建对象输出流//new ObjectOutputStream(OutputStream out): Creates an ObjectOutputStream that writes to the specified OutputStream.

oos = newObjectOutputStream(bout);//向对象输出流中写数据//void writeObject(Object obj): Write the specified object to the ObjectOutputStream.

oos.writeObject(obj);

}catch(IOException e) {

e.printStackTrace();

}finally{

close(oos);

close(bout);

}//反序列化

ByteArrayInputStream bin = null;

ObjectInputStream ois= null;try{//创建字节数组输入流//new ByteArrayInputStream(byte buf[]): Creates a ByteArrayInputStream so that it uses buf as its buffer array.

bin = newByteArrayInputStream(bout.toByteArray());//创建对象输入流//new ObjectInputStream(InputStream in): Creates an ObjectInputStream that reads from the specified InputStream.

ois = newObjectInputStream(bin);//从对象输入流中读取数据//Object readObject(): Read an object from the ObjectInputStream.

cloneObj =(T)ois.readObject();

}catch (IOException |ClassNotFoundException e) {

e.printStackTrace();

}finally{

close(ois);

close(bin);

}returncloneObj;

}//关闭流

private static voidclose(Closeable closeable){if(closeable != null){try{

closeable.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

}

public class SchoolSeri implementsSerializable{privateString name;privateStudentSeri stu;publicSchoolSeri(String name, StudentSeri stu) {this.name =name;this.stu =stu;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicStudentSeri getStu() {returnstu;

}public voidsetStu(StudentSeri stu) {this.stu =stu;

}

@OverridepublicString toString() {return "School{" +

"name='" + name + '\'' +

", stu=" + stu +

'}';

}

}public class StudentSeri implementsSerializable{privateString name;publicStudentSeri(String name) {this.name =name;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}

@OverridepublicString toString() {return "Student{" +

"name='" + name + '\'' +

'}';

}

}

END

java深度克隆_Java深入学习26:Java深度克隆相关推荐

  1. java中二叉树_java后端学习路线

    "学习真的是一个循序渐进的过程,也是一件需要坚持的事情.对于这篇文章,不同阶段的人可能有不同的理解,所以我把我整理的比较全面的java学习路线分享给大家,以供参考.下面的这个学习路线主要针对 ...

  2. java catch空指针异常处理_Java基础学习:java文件空指针异常处理

    在Java编程中,我们或多或少地会遇到一些程序异常的情况,为了不影响程序的正常执行,我们需要在程序发生异常的情况下,进行一些操作来防止造成更大的损失.例如在我们平时的除法运算中,被除数是不能为0的,如 ...

  3. java 线程起名字_java多线程学习三::::为什么要给线程起名字并且知道守护作用?...

    为什么要会线程起名字呢? 你如果拿到一连串的Thread-01,Thead-02我想你应该会疯掉,看以下代码 package rs.thread.day0504; /** * @auther rs * ...

  4. java新人培训_Java新人学习必要的步骤以及全套学习路线!

    原标题:Java新人学习必要的步骤以及全套学习路线! 想学Java,刚开始有没有觉得无从下手呢?其实Java的基础知识点,并不多,但是一定要吃透,因为这是为后续核心的学习打下一个良好的基础.简单来说, ...

  5. java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的

    本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...

  6. java回收类_Java的内存回收——Java引用的种类

    1.Java引用的种类 Java是面向对象的编程语言,一个Java程序往往需要创建大量的Java类,然后对各Java类创建大量的Java对象,再调用这些Java对象的属性和方法来操作它们. 程序员需要 ...

  7. java 元数据 注解_Java元数据总结:Java注释的使用和定义

    元数据从metadata一词译来,就是"关于数据的数据"的意思.越来越的开源框架都提供了"元数据"支持了,其实也就是注释支持.今天系统学习一下Java注释(Ja ...

  8. java干嘛_java是什么(Java到底能干嘛?)

    我刚开始学习Java的时候,很长一段时间都有这么个疑惑? Java到底是啥?它能干什么? 自己也看过不少的课程和书,大部分都是从Java的发展史开始讲,总之就是那些什么Java历史悠久,Java很优秀 ...

  9. java类描述_java笔记2:Java语言中的类和对象的描述

    在Java 语言中,除8 个基本数据类型值之外, 一切都是对象,而对象就是面向对象程序设计的中心. 对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还 ...

最新文章

  1. [Linux]安装node.js
  2. %3cphp和%3c php_关于 PHP 表单安全性
  3. 海量数据处理利器之Hash——在线邮件地址过滤
  4. 移动端弹出遮罩层禁止页面滚动,遮罩里面的框允许滚动如何实现。
  5. Oracle里面的用户user无法登录 LOCKED(TIMED)
  6. 优秀测试管理工具必备九大功能分析
  7. 6面向对象的程序设计
  8. 10,000 小时编程反思
  9. python excel数据可视化软件_excel是基础的数据分析与可视化工具
  10. 618买手机哪家强?苹果官方也来打折促销了
  11. C++求字符串长度的两种方法
  12. Python从list删除元素
  13. Java多线程(三)——多线程实现同步
  14. 夜神模拟器:adb命令
  15. C# 采用Automation控制自动拨打接听电话
  16. python之使用pyaudio录音和格式转化
  17. 如何将pdf文件压缩变小?
  18. java duplicate_Duplicate spring bean id
  19. Dropping Balls, UVa679
  20. Gnome桌面的录屏插件easyscreencast

热门文章

  1. MyEclipse 2014中 Window--customize perspective 功能 打不开的解决办法
  2. Ubuntu中搭建Hadoop2.5.2完全分布式系统(一)
  3. 这是EnterLib PIAB的BUG吗?
  4. Flex与.NET互操作(四):使用HttpService、URLReqeust和URLLoader加载/传输数据
  5. 网站设计常用技巧收集
  6. Axure RP 简介
  7. LINQ体验(6)——LINQ语句之Join和Order By
  8. java 搭建论坛_GitHub - NieShaoLiang/bbs: 基于spring boot的java论坛系统
  9. 关于微信红包的架构思考
  10. NGINX限流的一些思考