教你彻底学会Java序列化和反序列化
Java序列化是什么?
Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程。反序列化:客户端重文件,或者网络中获取到文件以后,在内存中重构对象。序列化:对象序列化的最重要的作用是传递和保存对象的时候,保证对象的完整性和可传递性。方便字节可以在网络上传输以及保存在本地文件。
为什么需要序列化和反序列化
实现分布式
核心在于RMI,可以利用对象序列化运行远程主机上的服务,实现运行的时候,就像在本地上运行Java对象一样。
实现递归保存对象
进行序列化的时候,单单并不是保存一个对象,而是递归的保存一整个对象序列,即递归保存,通过反序列化,可以递归的得到一整个对象序列。
序列信息可以永久保存
用于序列化的信息,可以永久保存为文件,或者保存在数据库中,在使用的时候,再次随时恢复到内存中,实现内存中的类的信息可以永久的保存。
数据格式统一
比照Linux的一切皆文件的思想,同时Java也是这样的思想,让数据格式尽可能的统一,让对象,文件,数据,等等许许多多不同的格式,都让其统一,以及保存。实现数据可以完整的传输和保存。然后进行反序列化还原,即,对象还是对象,文件还是文件。
实现Java序列化和反序列化
要进行反序列化需要实现一个接口。即 Serializabei接口。代码如下 需要转化的类
package common.lang;
import java.io.Serializable;
import org.apache.commons.lang3.builder.ToStringBuilder;import org.apache.commons.lang3.builder.ToStringStyle;
public class User1 implements Serializable{private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("name", name) .append("age", age) .toString(); }}
进行序列化,以及反序列化
package common.lang;
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;
public class SerializableDemo1 {public static void main(String[] args) throws Exception, IOException { //初始化对象 User1 user = new User1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 File file = new File("template"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); User1 newUser = (User1)ois.readObject(); System.out.println(newUser.toString()); }}
另一个序列化接口 Externalizable
继续实现Externalizable接口
package common.lang;
import java.io.Externalizable;import java.io.IOException;import java.io.ObjectInput;import java.io.ObjectOutput;
import org.apache.commons.lang3.builder.ToStringBuilder;import org.apache.commons.lang3.builder.ToStringStyle;
public class User1 implements Externalizable{private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("name", name) .append("age", age) .toString(); } @Override public void writeExternal(ObjectOutput out) throws IOException { // TODO Auto-generated method stub } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // TODO Auto-generated method stub }}
进行序列化以及反序列化
package common.lang;
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;
public class SerializableDemo1 {public static void main(String[] args) throws Exception, IOException { //初始化对象 User1 user = new User1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 File file = new File("template"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); User1 newUser = (User1)ois.readObject(); System.out.println(newUser.toString()); ois.close(); }}
查看输出的结构
common.lang.User1@6ef64f64[ name=yaomy age=23]common.lang.User1@184c9860[ name=<null> age=0]
根据输出的结果可以看到,对User1进行序列化然后再反序列化之后对象的属性都恢复成了默认值,即,之前那个对象的状态没有被持久保存下来,这就是Externalization和Serialization接口的区别,其中前者接口会被恢复成为默认值,后者接口不会恢复默认值。
如果需要恢复,这里就需要重写两个抽象方法,分别是writeExternal与readExternal两个抽象方法。
package common.lang;
import java.io.Externalizable;import java.io.IOException;import java.io.ObjectInput;import java.io.ObjectOutput;
import org.apache.commons.lang3.builder.ToStringBuilder;import org.apache.commons.lang3.builder.ToStringStyle;
public class User1 implements Externalizable{private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("name", name) .append("age", age) .toString(); } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); out.writeInt(age); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); age = in.readInt(); }}
package common.lang;
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;
public class SerializableDemo1 {public static void main(String[] args) throws Exception, IOException { //初始化对象 User1 user = new User1(); user.setName("yaomy"); user.setAge(23); System.out.println(user); //序列化对象到文件中 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template")); oos.writeObject(user); oos.close(); //反序列化 File file = new File("template"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); User1 newUser = (User1)ois.readObject(); System.out.println(newUser.toString()); ois.close(); }}
输出的结果
common.lang.User1@6cd66725[name=yaomyage=23
]
common.lang.User1@19160e64[name=yaomyage=23
]
静态变量的序列化
实例
public class Test implements Serializable { private static final long serialVersionUID = 1L; public static int staticVar = 5; public static void main(String[] args) { try { //初始时staticVar为5 ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("result.obj")); out.writeObject(new Test()); out.close(); //序列化后修改为10 Test.staticVar = 10; ObjectInputStream oin = new ObjectInputStream(new FileInputStream( "result.obj")); Test t = (Test) oin.readObject(); oin.close(); //再读取,通过t.staticVar打印新的值 System.out.println(t.staticVar); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
代码阐述一下过程,在main方法中,对象序列化以后,修改静态变量的数值,再把序列化后的对象读取出来,此时输出的值为10. 理解如下:打印的staticVar是从读取对象里获得的,打印10的原因是因为序列化时,不保存静态变量,只保存内存中的状态。此时修改静态变量的值,修改的是类中的值,输出的也是类中的值,和内存无关。
Transient关键字
Transient关键字,加上以后,可以阻止该变量被序列化到文件中,反序列化以后,变量的值设定为初始值。
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️
教你彻底学会Java序列化和反序列化相关推荐
- 理论 | 教你彻底学会Java序列化和反序列化
这是小小本周的第四篇 Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件 ...
- java 序列化概念和作用_结合代码详细解读Java序列化与反序列化概念理解
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...
Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化:对象序列化的最主要的用处就是在传递和保存对象 ...
- java序列化与反序列化(转)
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- java序列化和反序列化以及序列化ID的作用分析
java序列化和反序列化 一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一 ...
- java序列化和反序列化_Java恶意序列化背后的历史和动机
java序列化和反序列化 与Java的序列化机制相关的问题已广为人知. 有效的Java 1st Edition (第10章)和有效的Java 2nd Edition (第11章)的整个最后一章都专门讨 ...
- Java序列化与反序列化(一)
目录 序列化与反序列化 1.最简单的使用:Serializable 接口 2. 序列化 ID 的问题 3. 静态字段不会序列化 4. 屏蔽字段:transient 5. 父类的序列化 6. 自定义序列 ...
- Serializable详解(1):代码验证Java序列化与反序列化
说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...
- Java 序列化与反序列化
Java 序列化与反序列化 文章目录 Java 序列化与反序列化 1 序列化与反序列化的概念 2 核心类与关键字总览 3 序列化与反序列化的过程 3 应用示例 4 序列化版本号的作用 serialVe ...
最新文章
- Ubuntu18.04:错误整理
- 测试MindMotion 的 ISP功能 - 无法进入ISP功能
- 分布式实时日志分析解决方案ELK部署架构
- JavaScript设计模式(一)
- 计算机专业英语卷子,计算机专业英语A试卷.doc
- c++ 跳转到上级目录_Windows漏洞利用开发 第4部分:使用跳转定位Shellcode 模块
- 3、java中的数据类型和运算符
- face++算法工程实习生面试
- 模板消息 php实例,PHP微信模板消息操作示例
- 【ES9(2018)】for await...of
- 眨眼检测计算机不精确,基于OpenCV和Python错误的眨眼检测
- linux上卓懿应用商城王者荣耀键盘映射如何设置?
- JZOJ4722. 跳楼机
- win8.1装载windows和linux双系统
- 在学习少儿编程中体会AI乐趣
- Spring集成JPA提示Not an managed type
- linux编译ipp多线程,Linux下Intel IPP编程环境的配置
- 2019年美国计算机科学排名,最新!2019年USNews美国大学计算机专业排名
- MPC5748G S32_SDK_PA_RTM_3.0.0 GPIO 调试仿真设置
- imfindcircles
热门文章
- 按英语体育计算机创建透视表,数据透视表和数据透视图概述
- java 用户线程如何修改界面内容_java 加入一个线程、创建有响应的用户界面 。 示例代码...
- linux设备负责执行计划任务,Linux计划任务详解,很详细,每一行命令都有相对应的白话解释。...
- arm linux挂载ubi,挂载ubifs文件系统分区
- loadrunner之socket协议脚本编写
- 在Windows 下使用CodeBlocks 自带编译器实现对编译的优化
- 操作系统之文件管理:7、文件共享与文件保护(软连接、硬链接、口令保护、加密保护、访问控制)
- 496. 下一个更大元素 I/503. 下一个更大元素 II/739. 每日温度
- 从零开始学PowerShell(6)获取对象信息
- Kibana未授权访问漏洞记录(CVE-2019-7609,Kibana的RCE,原型链污染,端口:5601)