本篇博客内容:

  一、浅克隆(ShallowClone)和深克隆(DeepClone)

  二、序列化和反序列化实现深克隆

  三、封装序列化和反序列化操作

    ObjectOutputStream + 内存流ByteArrayOutputStream

  四、对象持久化到文件或从文件中读取对象

    ObjectOutputStream + FileOutputStream

一、浅克隆(ShallowClone)和深克隆(DeepClone)   <=返回目录

1.1、浅克隆和深克隆区别

package com.oy.shallowclone;

/*
浅克隆(ShallowClone)和深克隆(DeepClone)。 在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,
值类型包括int、double、byte、boolean、char等简单数据类型,
引用类型包括类、接口、数组等复杂类型。
浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。 实现clone方法的步骤
(1)实现Cloneable接口
(2)重写Object类中的clone()方法,重写时需定义为public
(3)在重写方法中,调用super.clone()
*/
public class Student implements Cloneable {
private int number; public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
} /*
@Override
public Object clone() {
Student stu = null;
try {
stu = (Student) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
*/
}

  

  测试

package com.oy.shallowclone;

public class StudentTest {
public static void main(String args[]) throws CloneNotSupportedException {
Student stu1 = new Student();
stu1.setNumber(12345); // stu1克隆出stu2
Student stu2 = (Student) stu1.clone(); System.out.println("学生1:" + stu1.getNumber()); //
System.out.println("学生2:" + stu2.getNumber()); // stu2.setNumber(54321); // 修改stu2 System.out.println("学生1:" + stu1.getNumber()); //
System.out.println("学生2:" + stu2.getNumber()); //
}
}

1.2、浅克隆

  Cat类

package com.oy.shallowclone;

public class Cat implements Cloneable {
private String name;
// getter和setter省略 @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

  Person类

package com.oy.shallowclone;

public class Person implements Cloneable {
private String name;
private Integer age;
private Cat cat;
// getter和setter省略 @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

  

  测试类

package com.oy.shallowclone;

public class PersonTest {
public static void main(String[] args) throws CloneNotSupportedException {
Cat cat = new Cat();
cat.setName("狸花"); Person per1 = new Person();
per1.setName("张三");
per1.setAge(10);
per1.setCat(cat); // per1克隆出per2
Person per2 = (Person) per1.clone(); System.out.println(per1.getName() + "-" + per1.getAge() + "-" + per1.getCat().getName()); // 张三-10-狸花
System.out.println(per2.getName() + "-" + per2.getAge() + "-" + per2.getCat().getName()); // 张三-10-狸花
System.out.println(per1.getName() == per2.getName()); // true
System.out.println(per1.getAge() == per2.getAge()); // true
System.out.println(per1.getCat() == per1.getCat()); // true // 修改per1
per1.setName("李四"); // per1的name属性保存另一个"字符串"的地址
per1.setAge(20);
cat.setName("小橘"); System.out.println(per1.getName() + "-" + per1.getAge() + "-" + per1.getCat().getName()); // 李四-20-小橘
System.out.println(per2.getName() + "-" + per2.getAge() + "-" + per2.getCat().getName()); // 张三-10-小橘
System.out.println(per1.getName() == per2.getName()); // false
System.out.println(per1.getAge() == per2.getAge()); // false
System.out.println(per1.getCat() == per1.getCat()); // true
}
}

  理论上String和Integer类型的属性的克隆也是浅克隆。但是,String和Integer是不可变的。所以,实际上当String和Integer类型的属性改变时,克隆对象不会跟着改变。

package com.oy.shallowclone;

/**
* 理论上String和Integer类型的属性的克隆也是浅克隆。
* 但是,String和Integer是不可变的。所以,实际上当String和Integer类型的属性改变时,克隆对象不会跟着改变。
*
* @author oy
*/
public class PersonTest2 {
public static void main(String[] args) throws CloneNotSupportedException {
Cat cat = new Cat();
cat.setName("狸花"); Person per1 = new Person();
String name = new String("张三");
per1.setName(name);
Integer age = new Integer("10");
per1.setAge(age);
per1.setCat(cat); // per1克隆出per2
Person per2 = (Person) per1.clone(); System.out.println(per1.getName() + "-" + per1.getAge() + "-" + per1.getCat().getName()); // 张三-10-狸花
System.out.println(per2.getName() + "-" + per2.getAge() + "-" + per2.getCat().getName()); // 张三-10-狸花
System.out.println(per1.getName() == per2.getName()); // true 说明是浅克隆
System.out.println(per1.getAge() == per2.getAge()); // true 说明是浅克隆
System.out.println(per1.getCat() == per1.getCat()); // true 说明是浅克隆 // 修改per1
name = new String("李四"); // 只是修改了name变量里面保存的地址值
age = new Integer("20"); // 只是修改了age变量里面保存的地址值
cat.setName("小橘"); System.out.println(per1.getName() + "-" + per1.getAge() + "-" + per1.getCat().getName()); // 张三-10-小橘
System.out.println(per2.getName() + "-" + per2.getAge() + "-" + per2.getCat().getName()); // 张三-10-小橘
System.out.println(per1.getName() == per2.getName()); // true
System.out.println(per1.getAge() == per2.getAge()); // true
System.out.println(per1.getCat() == per1.getCat()); // true
}
}

1.3、深克隆

  Teacher类

package com.oy.deepclone;

class Teacher implements Cloneable {
private int age;
private String name; // getter和setter省略 @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

  

  Student类

package com.oy.deepclone;

public class Student implements Cloneable {
private int age;
private String name;
private Teacher teacher; // getter和setter省略 @Override
public Object clone() throws CloneNotSupportedException {
// 这一步返回的这个student还只是一个浅克隆,
Student student = (Student) super.clone();
// 然后克隆的过程中获得这个克隆的student,然后调用这个getTeacher这个方方法得到这个Teacher对象。
// 然后实现克隆。在设置到这个student中的Teacher。
// 这样实现了双层克隆使得那个teacher对象也得到了复制。
student.setTeacher((Teacher) student.getTeacher().clone());
// 双层克隆使得那个teacher对象也得到了复制
return student;
}
}

  测试类

package com.oy.deepclone;

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher();
teacher.setAge(40);
teacher.setName("teacher zhang"); Student stu1 = new Student();
stu1.setAge(10);
stu1.setName("张三");
stu1.setTeacher(teacher); //stu1深克隆出stu2
Student stu2 = (Student) stu1.clone(); // 这里是深复制,所以这时候Student中的teacher就是teacher这个对象的一个复制,就和student2是Student的一个复制
// 所以下面teacher.setName只是对他原来的这个对象更改,但是复制的那个并没有更改
System.out.println(stu1.getName() + "-" + stu1.getAge() + "-" + stu1.getTeacher().getName());//张三-10-teacher zhang
System.out.println(stu2.getName() + "-" + stu2.getAge() + "-" + stu2.getTeacher().getName());//张三-10-teacher zhang // 修改stu1
stu1.setName("李四");
stu1.setAge(20);
teacher.setName("teacher wang"); System.out.println(stu1.getName() + "-" + stu1.getAge() + "-" + stu1.getTeacher().getName());//李四-20-teacher wang
System.out.println(stu2.getName() + "-" + stu2.getAge() + "-" + stu2.getTeacher().getName());//张三-10-teacher zhang
}
}

二、序列化和反序列化实现深克隆   <=返回目录

  Car类

public class Car implements Serializable {
private static final long serialVersionUID = -7633040136520448512L;
private String name;
private String color; public Car() {} public Car(String name, String color) {
this.name = name;
this.color = color;
} // getter和setter方法省略 @Override
public String toString() {
return "Car [name=" + name + ", color=" + color + "]";
}
}

  Person类

public class Person implements Serializable {
private static final long serialVersionUID = 4792126594710124401L;
private String name;
private int age;
private Car car; public Person() {} public Person(String name, int age) {
this.name = name;
this.age = age;
} public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
} // getter和setter方法省略 @Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}

  工具类:使用序列化和反序列化实现对象的克隆

package com.oy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; /**
* 工具类:使用序列化和反序列化实现对象的克隆
*
* @author oy
* @version 1.0
* @date 2018年8月9日
* @time 下午8:59:23
*/
public class cloneUtil {
private cloneUtil() {
} @SuppressWarnings("unchecked")
public static <T extends Serializable> T cloneObject(T obj) {
T cloneObj = null; // 序列化
ByteArrayOutputStream bout = null;
ObjectOutputStream oos = null;
try {
bout = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(oos);
close(bout);
} // 反序列化
ByteArrayInputStream bin = null;
ObjectInputStream ois = null;
try {
bin = new ByteArrayInputStream(bout.toByteArray());
ois = new ObjectInputStream(bin);
cloneObj = (T) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
close(ois);
close(bin);
} return cloneObj;
} private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

  测试

/**
* 序列化和反序列化实现深克隆
*
* @author oy
* @version 1.0
* @date 2018年8月9日
* @time 下午8:58:53
*/
public class Test {
public static void main(String[] args) {
Car car = new Car("BYD", "black");
Person p1 = new Person("张三", 20, car);
Person p2 = cloneUtil.cloneObject(p1); System.out.println("P1:" + p1);//P1:Person [name=张三, age=20, car=Car [name=BYD, color=black]]
System.out.println("p2:" + p2);//p2:Person [name=张三, age=20, car=Car [name=BYD, color=black]] if (p2 != null) {
car.setName("宝马");
car.setColor("red");
} System.out.println("P1:" + p1);//P1:Person [name=张三, age=20, car=Car [name=宝马, color=red]]
System.out.println("p2:" + p2);//p2:Person [name=张三, age=20, car=Car [name=BYD, color=black]]
}
}

三、封装序列化和反序列化操作   <=返回目录

3.1、封装序列化和反序列化操作

package com.oy;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List; /**
* 序列化,反序列化工具类。用于转换byte[]和对象
*
* @author oy
* @date 2019年6月3日 下午11:46:53
* @version 1.0.0
*/
public class SerializeUtil { public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
} finally {
close(oos);
close(baos);
}
return null;
} public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(bais);
close(ois);
}
return null;
} /**
* 序列化 list 集合
*
* @param list
* @return
*/
public static byte[] serializeList(List<?> list) { if (list == null || list.size() <= 0) {
return null;
}
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
byte[] bytes = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
for (Object obj : list) {
oos.writeObject(obj);
}
bytes = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(oos);
close(baos);
}
return bytes;
} /**
* 反序列化 list 集合
*
* @param lb
* @return
*/
public static List<?> unserializeList(byte[] bytes) {
if (bytes == null) {
return null;
} List<Object> list = new ArrayList<Object>();
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
while (bais.available() > 0) {
Object obj = (Object) ois.readObject();
if (obj == null) {
break;
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(bais);
close(ois);
}
return list;
} /**
* 关闭io流对象
*
* @param closeable
*/
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

  

3.2、cloneUtil类改为:

public class cloneUtil {
private cloneUtil() {} @SuppressWarnings("unchecked")
public static <T extends Serializable> T cloneObject(T obj) {
// 序列化
byte[] bs = SerializeUtil.serialize(obj); // 反序列化
return (T) SerializeUtil.unserialize(bs);
}
}

四、对象持久化到文件或从文件中读取对象   <=返回目录

package com.oy;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; /**
* 序列化和反序列化
*
* @author oy
* @version 1.0
* @date 2018年8月9日
* @time 下午8:58:32
*/
public class serialDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建Person对象
Car car = new Car("BMW", "black");
Person p = new Person("张三abc", 20, car); write(p);
Object obj = read(); // Person [name=张三abc, age=20, car=Car [name=BMW, color=black]]
System.out.println(obj); } private static Object read() throws FileNotFoundException, IOException, ClassNotFoundException {
// 创建反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
// 反序列化
Object obj = ois.readObject();
// 释放资源
ois.close();
return obj;
} private static void write(Object obj) throws FileNotFoundException, IOException {
// 创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
// 序列化
oos.writeObject(obj);
// 释放资源
oos.close();
}
}

参考:

  (1)SerializeUtil 序列化,反序列化工具类

  (2)Java基础学习总结——Java对象的序列化和反序列化

java浅克隆和深克隆,序列化和反序列化实现深克隆(封装序列化和反序列化操作)的更多相关文章

  1. Java序列化的几种方式以及序列化的作用

    Java序列化的几种方式以及序列化的作用 本文着重讲解一下Java序列化的相关内容. 如果对Java序列化感兴趣的同学可以研究一下. 一.Java序列化的作用    有的时候我们想要把一个Java对象 ...

  2. java中POJO类和DTO类都要实现序列化

    java中POJO类和DTO类都要实现序列化 java中POJO类和DTO类都要实现序列化 java中POJO类和DTO类都要实现序列化 序列化:序列化是将对象转换为容易传输的格式的过程.例如,可以序 ...

  3. Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题【转】

    Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题 http://blog.didispace.com/Spring-Boot-And-Feign- ...

  4. c#序列化感悟(重点讲讲二进制序列化)

    序列化是一种通过将对象转化为字节流,从而达到储存对象,或者将对象传输到内存,数据库或文件的一个过程,主要用途是保存对象的状态(包括对象的数据),方便对对象的重建,反之读取就是反序列化. 三种序列化类型 ...

  5. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. Java.io下的方法是对磁盘上的文件进行磁盘操作

    File类(java.io.*)可表示一个文件,也有可能是一个目录(在JAVA中文件和目录都属于这个类中,而且区分不是非常的明显). Java.io下的方法是对磁盘上的文件进行磁盘操作,但是无法读取文 ...

  7. Java基础知识强化之IO流笔记65:序列化流 和 反序列化流

    1. 什么是 序列化 和 反序列化 ?     序列化 (Serialization):将对象的状态信息转换为可以存储或传输的形式的过程.比如转化为二进制.xml.json等的过程. 在序列化期间,对 ...

  8. java 浅克隆 深克隆

    对象的克隆是java的一项高级技术,他可以根据给定的对象,获得与其完全相同的另一个对象. 1.浅克隆主要是复制对象的值 2.深克隆:当类存在聚合关系的时候,克隆就必须考虑聚合对象的克隆,可以复制引用类 ...

  9. java 浅克隆(浅复制)和深克隆(深复制)

    http://www.voidcn.com/blog/u011380813/article/p-6161450.html https://gold.xitu.io/entry/570d89651ea4 ...

随机推荐

  1. c++ 加载资源文件

    int _tmain(int argc, _TCHAR* argv[]) { HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_DATA1), ...

  2. aiXcoder安装&使用

    1.官网下载 https://www.aixcoder.com/#/setting 1.1介绍 1.2选择对应的下载版本 1.3安装&注册(需关闭IDEA) 安装完进行手机/邮箱注册,下载对应 ...

  3. 本机添加DNS映射

    开发项目时本地进行代码编写测试,需要与服务器主机进行DNS映射. 本地主机添加DNS映射步骤 一:复制备份hosts文件 找到C:\Windows\System32\drivers\etc下的host ...

  4. 《React+Redux前端开发实战》笔记1:不涉及React项目构建的Hello World案例

    本小节实现一个不涉及项目构建的Hello World. [React的第一个Hello World网页] 源码地址:https://jsfiddle.net/allan91/2h1sf0ky/8/ & ...

  5. jenkins自动化测试Email Extension邮件模板 及可用参数TEST_COUNTS ,FAILED_TESTS详细说明

    先列出模板内容: <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <t ...

  6. 深入理解java:2.3. 并发编程 java.util.concurrent包

    JUC java.util.concurrent包, 这个包是从JDK1.5开始引入的,在此之前,这个包独立存在着,它是由Doug Lea开发的,名字叫backport-util-concurrent ...

  7. [Web 前端] 026 jQuery 初探

    目录 1. jQuery 简介 2. jQuery 的简单操作 2.1 jQuery 选择器 2.1.1 简介 2.1.2 基础选择器 2.2 过滤获取 2.3 父子关系获取 3. jQuery 元素 ...

  8. BAT推荐免费下载JAVA转型大数据开发全链路教程(视频+源码)价值19880元

    如今随着环境的改变,物联网.AI.大数据.人工智能等,是未来的大趋势,而大数据是这些基石,万物互联,机器学习都是大数据应用场景! 为什么要学习大数据?我们JAVA到底要不要转型大数据? 好比问一个程序 ...

  9. 网络流 ISAP算法

    网络流问题: 我自己理解,在流网络中,在不违背容量限制的条件下,解决各种从源点到汇点的问题. ISAP算法概念: 据说不会有卡ISAP时间的题目---时间复杂度O(E^2*V) 首先原理都是基于不断寻 ...

  10. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...