本篇博客内容:

  一、浅克隆(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. 修改了Ubuntu下的/usr目录权限,导致不能使用sudo命令的修复-----转载

    刚开始运行sudo时,报了下面这个错误 sudo: must be setuid root,于是上网找解决方法,搜索出来的都是这样解决的 ls -l  /usr/bin/sudochown root: ...

  2. Numpy——进阶篇

    impoort numpy as np arr=np.arange(10) #输出奇数 arr[arr%2==1] #将arr中的所有奇数替换为-1,而不改变arr out=np.where(arr% ...

  3. Linux window 安装tomcat各版本下载地址

    1.地址 https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/

  4. [转帖]探秘华为(二):华为和H3C(华三)的分道扬镳

    探秘华为(二):华为和H3C(华三)的分道扬镳 https://baijiahao.baidu.com/s?id=1620781715767053734&wfr=spider&for= ...

  5. 关于this与e.target区别以及data-*属性

    1 this与event.target 在编写事件函数时可以传入一个event参数,even参数可以使用一个target属性如even.target用以调用,其作用是指向返回事件的目标节点(触发该事件 ...

  6. django基础知识之认识MVT MVC??

    MVT Django是一款python的web开发框架 与MVC有所不同,属于MVT框架 m表示model,负责与数据库交互 v表示view,是核心,负责接收请求.获取数据.返回结果(相当于mvc的c ...

  7. 34. Find First and Last Position of Element in Sorted Array (JAVA)

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  8. 初学ctypes:打开进程并返回相关信息

    直接上代码: 1. my_debugger_defines.py 定义相关结构体(在后面创建进程及返回信息时,传参可用到) from ctypes import * # Let's map the M ...

  9. Spring基础18——通过注解配置bean之间的关联关系

    1.组件装配 <context:component-scan>元素还会自动注册AutowiredAnnotaionBeanPostProcessor实例,这是一个bean的后置处理器,该实 ...

  10. Nginx 配置状态信息虚拟主机

    可以在浏览器中查看并发数量 [root@Liangenyu conf]# vim nginx.conf server { listen 80; server_name status.etiantian ...