Java序列化和反序列化(详解)
一、理解Java序列化和反序列化
Serialization(序列化):将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。
deserialization(反序列化):将保存在磁盘文件中的java字节码重新转换成java对象称为反序列化。
二、序列化和反序列化的应用
两个进程在远程通信时,可以发送多种数据,包括文本、图片、音频、视频等,这些数据都是以二进制序列的形式在网络上传输。
java是面向对象的开发方式,一切都是java对象,想要在网络中传输java对象,可以使用序列化和反序列化去实现,发送发需要将java对象转换为字节序列,然后在网络上传送,接收方收到字符序列后,会通过反序列化将字节序列恢复成java对象。
java序列化的优点:
- 实现了数据的持久化,通过序列化可以把数据持久地保存在硬盘上(磁盘文件)。
- 利用序列化实现远程通信,在网络上传输字节序列。
三、序列化和反序列化地实现
1.JDK类库提供的序列化API:
- java.io.ObjectOutputStream
表示对象输出流,其中writeObject(Object obj)方法可以将给定参数的obj对象进行序列化,将转换的一连串的字节序列写到指定的目标输出流中。 - java.io.ObjectInputStream
该类表示对象输入流,该类下的readObject(Object obj)方法会从源输入流中读取字节序列,并将它反序列化为一个java对象并返回。
序列化要求:
实现序列化的类对象必须实现了Serializable类或Externalizable类才能被序列化,否则会抛出异常。
实现java序列化和反序列化的三种方法:
现在要对student类进行序列化和反序列化,遵循以下方法:
方法一:若student类实现了serializable接口,则可以通过objectOutputstream和objectinputstream默认的序列化和反序列化方式,对非transient的实例变量进行序列化和反序列化。
方法二:若student类实现了serializable接口,并且定义了writeObject(objectOutputStream out)和
readObject(objectinputStream in)方法,则可以直接调用student类的两种方法进行序列化和反序列化。
方法三:若student类实现了Externalizable接口,则必须实现readExternal(Objectinput in)和writeExternal(Objectoutput out)方法进行序列化和反序列化。
JDK类库中的序列化步骤:
第一步:创建一个输出流对象,它可以包装一个输出流对象,如:文件输出流。
ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream("E:\\JavaXuLiehua\\Student\\Student1.txt"));
第二步:通过输出流对象的writeObject()方法写对象
out.writeObject("hollo word");
out.writeObject("happy")
JDK中反序列化操作:
第一步:创建文件输入流对象
ObjectInputStream in = new ObjectInputStream(new fileInputStream("E:\\JavaXuLiehua\\Student\\Student1.txt"));
第二步:调用readObject()方法
String obj1 = (String)in.readObject();
String obj2 = (String)in.readObject();
为了保证正确读取数据,对象输出流写入对象的顺序与对象输入流读取对象的顺序一致。
Student类序列化和反序列化演示:
1.先创建一个继承了serializable类的student类
import java.io.Serializable; //导入io包下的序列化类//创建实现序列化接口的学生类
public class Student implements Serializable {//私有化成员变量private String name;private char sex;private int year;private double gpa;public Student(){ //无参构造}public Student(String name,char sex,int year,double gpa){//参数给属性赋值this.name = name;this.sex = sex;this.year = year;this.gpa = gpa;}//重写set和getpublic String getName() {return name;}public void setName(String name) {this.name = name;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public double getGpa() {return gpa;}public void setGpa(double gpa) {this.gpa = gpa;}
}
把Student类的对象序列化到txt文件(E:\\JavaXuLiehua\\Student\\Student1.txt)中,并对文件进行反序列化:
import java.io.*;
import java.io.Externalizable;
/*
把student类对象序列化到文件E:\\JavaXuLiehua\\Student\\Student1.txt*/
public class UserStudent {public static void main(String[] args) throws IOException {Student st = new Student("Tom",'M',20,3.6); //实例化student类//判断Student1.txt是否创建成功File file = new File("E:\\JavaXuLiehua\\Student\\Student1.txt");if(file.exists()) {System.out.println("文件存在");}else{//否则创建新文件file.createNewFile();}try {//Student对象序列化过程FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos);//调用 ObjectOutputStream 中的 writeObject() 方法 写对象oos.writeObject(st);oos.flush(); //flush方法刷新缓冲区,写字符时会用,因为字符会先进入缓冲区,将内存中的数据立刻写出fos.close();oos.close();//Student对象反序列化过程FileInputStream fis = new FileInputStream(file);//创建对象输入流ObjectInputStream ois = new ObjectInputStream(fis);//读取对象Student st1 = (Student) ois.readObject(); //会抛出异常(类找不到异常)System.out.println("name = " + st1.getName());System.out.println("sex = " + st1.getSex());System.out.println("year = " + st1.getYear());System.out.println("gpa = " + st1.getGpa());ois.close();fis.close();}catch (ClassNotFoundException e){e.printStackTrace();}}
}
查看txt文件,结果如下:
sr JavaxulieHua.Studentd9Q藿Hf D gpaC sexI yearL namet Ljava/lang/String;xp@ 烫烫掏 M t Tom
可以看出其中的内容是不容易阅读的,只能通过反序列化读取。
四、transient关键字
transient关键字表示有理的,被修饰的数据不能进行序列化
这里不做详细介绍,修改情况如下:
private transient char sex; //被transient关键字修饰,不参与序列化
运行结果如下:
文件存在
name = Tom
sex =
year = 20
gpa = 3.6
此时可以看见,被transient关键字修饰的变量sex并没有被序列化,返回了空值。
五、Externalizable接口实现序列化与反序列化
Externalizable接口继承Serializable接口,实现Externalizable接口需要实现readExternal()方法和writeExternal()方法,这两个方法是抽象方法,对应的是serializable接口的readObject()方法和writeObject()方法,可以理解为把serializable的两个方法抽象出来。Externalizable没有serializable的限制,static和transient关键字修饰的属性也能进行序列化。
具体代码实现如下:
复制对象student命名为student1,在里面重写writeExternal()方法和readExternal()方法,如下:
@Override//对抽象方法进行重写public void writeExternal(ObjectOutput out) throws IOException{out.writeObject(name);out.writeObject(sex);out.writeObject(year);out.writeObject(gpa);}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {name = (String) in.readObject();sex = (char) in.readObject();year = (int) in.readObject();gpa = (double) in.readObject();}
相应的测试方法里面调用这两种方法的时候,直接调用writeObject()方法和readObject()方法即可,重写的writeExternal()和readExternal()方法会自动执行。
FileOutputStream fos1 = new FileOutputStream(file1);ObjectOutputStream oos1 = new ObjectOutputStream(fos1);//调用 ObjectOutputStream 中的 writeObject() 方法 写对象oos1.writeObject(st); //会自动执行重写的writeExternal()方法
FileInputStream fis1 = new FileInputStream(file1);//创建对象输入流ObjectInputStream ois1 = new ObjectInputStream(fis1);//读取对象//会自动执行readExternal()方法Student1 st1 = (Student1) ois1.readObject(); //会抛出异常(类找不到异常)
虽然student1类里的sex属性被static或transient修饰,但依旧被序列化,结果如下:
文件存在
name = Tom
sex = M
year = 20
gpa = 3.6
Java序列化和反序列化(详解)相关推荐
- Java 序列化和反序列化详解完整版
目录 一.序列化 1.1.Serialization(序列化): 1.2.deserialization(反序列化) 二.序列化和反序列化的应用 java序列化的优点: 三.序列化和反序列化地实现 3 ...
- Java序列化与反序列化详解
面试官:兄弟,说说你对transient的理解和感悟 哪吒:what?还有感悟? 先说结论,在序列化.反序列化时,被transient关键字修饰的成员属性变量不会被序列化. 面试官:这就完了? 哪吒: ...
- Java对象序列化详解6,Java对象的序列化与反序列化详解
把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种途径: Ⅰ . 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中 Ⅱ. 在网 ...
- 对象的序列化与反序列化详解
[1] 序列化与反序列化 如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中,或者在网络传输 Java 对象,这些场景都需要用到序列化. 简单来说: 序列化:将数据结构或对象转换成二 ...
- C#序列化与反序列化详解
什么是序列化以及如何实现序列化? 序列化是通过将对象转换为字节流,从而存储对象或将对象传输到内存,数据库或文件的过程.主要用途是保存对象的状态,包括对象的数据,以便能够在需要是重建对象.反向过程称为 ...
- Serializable详解(1):代码验证Java序列化与反序列化
说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...
- php 序列化 java_PHP--序列化与反序列化详解
PHP--序列化与反序列化详解 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 所有php里面的值都可以使用函数seria ...
- Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...
Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化:对象序列化的最主要的用处就是在传递和保存对象 ...
- php中对象怎么访问i属性_PHP--序列化与反序列化详解
PHP--序列化与反序列化详解 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 学到网络安全的时候用到了序列化和反序列化的 ...
最新文章
- Accurate circular consensus long-read sequencing improves variant detection and assembly of a human
- Safari回传值给应用程序
- 写程序的一些感想和教训
- pyspark sparksession_PySpark 处理数据和数据建模
- Java JDBC中的Statement和PreparedStatement
- AndroidStudio是最难用的IDE,没有之一
- mysql的bht_BHT
- 科学计算机算ph,科学计算器TechCalc v4.8.0特别高级会员版
- 控制系统matlab计算及仿真,控制系统MATLAB计算及仿真实训
- 大数据综合案例-网站日志分析
- 天正菜单栏不见了怎么显示出来_天正建筑菜单栏不见了怎么调出来? _ 设计学院_设计软件教程自学网...
- mysql 查看校对集,MySQL校对集
- 可见光波长和颜色的对应关系
- Java Test Fore
- 【C语言】计算一元二次方程的解
- docker进入容器时报错 Error response from daemon: Container xxx is restarting, wait until the container is
- 华为云数据库实验-openGauss金融场景化实验出现的问题
- java从json数组中提取数据,从JSON数组中提取数据
- python第三方包安装方法
- 2021-02-03 字符串上的小练习题