java深度克隆_Java深入学习26:Java深度克隆
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深度克隆相关推荐
- java中二叉树_java后端学习路线
"学习真的是一个循序渐进的过程,也是一件需要坚持的事情.对于这篇文章,不同阶段的人可能有不同的理解,所以我把我整理的比较全面的java学习路线分享给大家,以供参考.下面的这个学习路线主要针对 ...
- java catch空指针异常处理_Java基础学习:java文件空指针异常处理
在Java编程中,我们或多或少地会遇到一些程序异常的情况,为了不影响程序的正常执行,我们需要在程序发生异常的情况下,进行一些操作来防止造成更大的损失.例如在我们平时的除法运算中,被除数是不能为0的,如 ...
- java 线程起名字_java多线程学习三::::为什么要给线程起名字并且知道守护作用?...
为什么要会线程起名字呢? 你如果拿到一连串的Thread-01,Thead-02我想你应该会疯掉,看以下代码 package rs.thread.day0504; /** * @auther rs * ...
- java新人培训_Java新人学习必要的步骤以及全套学习路线!
原标题:Java新人学习必要的步骤以及全套学习路线! 想学Java,刚开始有没有觉得无从下手呢?其实Java的基础知识点,并不多,但是一定要吃透,因为这是为后续核心的学习打下一个良好的基础.简单来说, ...
- java display.getdefault()_java基础(十一 )-----反射——Java高级开发必须懂的
本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...
- java回收类_Java的内存回收——Java引用的种类
1.Java引用的种类 Java是面向对象的编程语言,一个Java程序往往需要创建大量的Java类,然后对各Java类创建大量的Java对象,再调用这些Java对象的属性和方法来操作它们. 程序员需要 ...
- java 元数据 注解_Java元数据总结:Java注释的使用和定义
元数据从metadata一词译来,就是"关于数据的数据"的意思.越来越的开源框架都提供了"元数据"支持了,其实也就是注释支持.今天系统学习一下Java注释(Ja ...
- java干嘛_java是什么(Java到底能干嘛?)
我刚开始学习Java的时候,很长一段时间都有这么个疑惑? Java到底是啥?它能干什么? 自己也看过不少的课程和书,大部分都是从Java的发展史开始讲,总之就是那些什么Java历史悠久,Java很优秀 ...
- java类描述_java笔记2:Java语言中的类和对象的描述
在Java 语言中,除8 个基本数据类型值之外, 一切都是对象,而对象就是面向对象程序设计的中心. 对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还 ...
最新文章
- [Linux]安装node.js
- %3cphp和%3c php_关于 PHP 表单安全性
- 海量数据处理利器之Hash——在线邮件地址过滤
- 移动端弹出遮罩层禁止页面滚动,遮罩里面的框允许滚动如何实现。
- Oracle里面的用户user无法登录 LOCKED(TIMED)
- 优秀测试管理工具必备九大功能分析
- 6面向对象的程序设计
- 10,000 小时编程反思
- python excel数据可视化软件_excel是基础的数据分析与可视化工具
- 618买手机哪家强?苹果官方也来打折促销了
- C++求字符串长度的两种方法
- Python从list删除元素
- Java多线程(三)——多线程实现同步
- 夜神模拟器:adb命令
- C# 采用Automation控制自动拨打接听电话
- python之使用pyaudio录音和格式转化
- 如何将pdf文件压缩变小?
- java duplicate_Duplicate spring bean id
- Dropping Balls, UVa679
- Gnome桌面的录屏插件easyscreencast
热门文章
- MyEclipse 2014中 Window--customize perspective 功能 打不开的解决办法
- Ubuntu中搭建Hadoop2.5.2完全分布式系统(一)
- 这是EnterLib PIAB的BUG吗?
- Flex与.NET互操作(四):使用HttpService、URLReqeust和URLLoader加载/传输数据
- 网站设计常用技巧收集
- Axure RP 简介
- LINQ体验(6)——LINQ语句之Join和Order By
- java 搭建论坛_GitHub - NieShaoLiang/bbs: 基于spring boot的java论坛系统
- 关于微信红包的架构思考
- NGINX限流的一些思考