Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >对象的序列化与反序列化

对象的序列化与反序列化

作者头像
拾点阳光
发布于 2018-05-11 03:44:29
发布于 2018-05-11 03:44:29
1.2K00
代码可运行
举报
文章被收录于专栏:码云1024码云1024
运行总次数:0
代码可运行

对象的序列化就是将Object转换成byte序列,反之叫做对象的反序列化

1.序列化流:

ObjectOutputStream,是过滤流----->writeObject

反序列化流:

ObjectInputStream ------->readObject

2.序列化接口:

Serializable

对象必须实现序列化接口,才能进行序列化,否则将会出现异常

这个接口没有任何方法,只是一个标准

3.一个类实现了序列化接口,子类也就都能进行序列化了

java.io 接口 Serializable

public interface Serializable

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和恢复超类型的公用 (public)、受保护的 (protected) 和(如果可访问)包 (package) 字段的状态。仅在子类型扩展的类有一个可访问的无参数构造方法来初始化该类的状态时,才可以假定子类型有此职责。如果不是这种情况,则声明一个类为可序列化类是错误的。该错误将在运行时检测到。

在反序列化过程中,将使用该类的公用或受保护的无参数构造方法初始化不可序列化类的字段。可序列化的子类必须能够访问无参数构造方法。可序列化子类的字段将从该流中恢复。

当遍历一个图形时,可能会遇到不支持 Serializable 接口的对象。在此情况下,将抛出 NotSerializableException,并将标识不可序列化对象的类。

在序列化和反序列化过程中需要特殊处理的类必须使用下列准确签名来实现特殊方法:

 private void writeObject(java.io.ObjectOutputStream out)

     throws IOException

 private void readObject(java.io.ObjectInputStream in)

     throws IOException, ClassNotFoundException;

 private void readObjectNoData()

     throws ObjectStreamException;

writeObject 方法负责写入特定类的对象的状态,以便相应的 readObject 方法可以恢复它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream,状态可以被保存。

readObject 方法负责从流中读取并恢复类字段。它可以调用 in.defaultReadObject 来调用默认机制,以恢复对象的非静态和非瞬态字段。defaultReadObject 方法使用流中的信息来分配流中通过当前对象中相应指定字段保存的对象的字段。这用于处理类演化后需要添加新字段的情形。该方法本身不需要涉及属于其超类或子类的状态。通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream,状态可以被保存。

在序列化流不列出给定类作为将被反序列化对象的超类的情况下,readObjectNoData 方法负责初始化特定类的对象状态。这在接收方使用的反序列化实例类的版本不同于发送方,并且接收者版本扩展的类不是发送者版本扩展的类时发生。在序列化流已经被篡改时也将发生;因此,不管源流是“敌意的”还是不完整的,readObjectNoData 方法都可以用来正确地初始化反序列化的对象。

将对象写入流时需要指定要使用的替代对象的可序列化类,应使用准确的签名来实现此特殊方法:

 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;

此 writeReplace 方法将由序列化调用,前提是如果此方法存在,而且它可以通过被序列化对象的类中定义的一个方法访问。因此,该方法可以拥有私有 (private)、受保护的 (protected) 和包私有 (package-private) 访问。子类对此方法的访问遵循 java 访问规则。

在从流中读取类的一个实例时需要指定替代的类应使用的准确签名来实现此特殊方法。

 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

此 readResolve 方法遵循与 writeReplace 相同的调用规则和访问规则。

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 -- serialVersionUID 字段作为继承成员没有用处。数组类不能声明一个明确的 serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配 serialVersionUID 值的要求。

对象的序列化的案例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 package zhang;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Student implements Serializable{
 6     
 7     private String stuno;
 8     private String stuname;
 9     
10     /* 被transient修饰后,该成员变量就不会再参与JVM默认序列化与反序列化的操作。
11      * 并不代表不可以进行序列化,也可以单独的进行序列化。    
12      * 因为并非所有的元素都要参与序列化,所以在网络传输的效率就会提高。*/    
13     private transient int stuage;
14     
15     
16     public String getStuno() {
17         return stuno;
18     }
19     public void setStuno(String stuno) {
20         this.stuno = stuno;
21     }
22     public String getStuname() {
23         return stuname;
24     }
25     public void setStuname(String stuname) {
26         this.stuname = stuname;
27     }
28     public int getStuage() {
29         return stuage;
30     }
31     public void setStuage(int stuage) {
32         this.stuage = stuage;
33     }
34     
35     public Student(){}
36     
37     public Student(String stuno, String stuname, int stuage) {
38         super();
39         this.stuno = stuno;
40         this.stuname = stuname;
41         this.stuage = stuage;
42     }
43     public String toString() {
44         return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
45                 + stuage + "]";
46     }
47     
48     private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{
49         s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作。
50         s.writeInt(stuage);//自己完成序列化。
51     }
52     
53     private void readObject(java.io.ObjectInputStream s)throws java.io.IOException,ClassNotFoundException{
54         s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作
55         this.stuage=s.readInt();//自己完成stuage的反序列化操作
56     }
57     
58     
59 }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 package zhang;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileOutputStream;
 7 import java.io.IOException;
 8 import java.io.ObjectInputStream;
 9 import java.io.ObjectOutputStream;
10 
11 /**
12  * 对象序列化
13  * */
14 public class Main {
15     public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
16         File file=new File("d://obj.dat");
17         if(!file.exists()){
18             file.createNewFile();
19         }
20         FileOutputStream fos=new FileOutputStream(file);
21         //1.对象的序列化
22         ObjectOutputStream oos=new ObjectOutputStream(fos);
23         Student stu=new Student("10001","张三",20);
24         oos.writeObject(stu);
25         oos.flush();
26         oos.close();
27         fos.close();
28         
29         //2.对象的反序列化
30         FileInputStream fis=new FileInputStream(file);
31         ObjectInputStream ois=new ObjectInputStream(fis);
32         Student stu2=new Student();
33         stu2=(Student)ois.readObject();
34         System.out.println(stu2.toString());
35         ois.close();
36         
37     }
38 }

输出:Student [stuno=10001, stuname=张三, stuage=20]

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-10-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
序列化/反序列化,我忍你很久了,淦!
上次不知道是哪个小伙伴留言说,关于对象 「序列化和反序列化」 这一块有点糊,能不能像之前梳理一样整理一波。
Java技术江湖
2020/06/16
8530
序列化/反序列化,我忍你很久了,淦!
【Java】Java序列化和反序列化
在Java中,序列化是将对象的状态写入字节流的机制。它主要用于Hibernate、RMI、JPA、EJB和JMS技术中。
人不走空
2024/06/28
2120
【Java】Java序列化和反序列化
Java——对象序列化(基本概念、序列化操作、反序列化、transient)
对象序列化指的是将在内存中保存的对象变为二进制数据流,这样对象可以保存在文件中或进行各种传输操作。要让类对象可被序列化,需要实现java.io.Serializable接口,此接口没有方法定义,属于标识接口。
Winter_world
2022/05/08
1.2K0
Java——对象序列化(基本概念、序列化操作、反序列化、transient)
Serializable详解(1):代码验证Java序列化与反序列化
通过实现java.io.Serializable interface接口来序列化一个类。
宜信技术学院
2020/03/11
1.4K0
文件输入输出处理(六)-序列化和反序列化
使用ObjectOutputStream 类的 writeObject(Object obj)方法
化羽羽
2022/10/28
3840
JAVA 对象序列化(一)——Serializable
http://www.cnblogs.com/chenfei0801/archive/2013/04/05/3001149.html
bear_fish
2018/09/19
5670
序列化和反序列化的底层实现原理是什么?
序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问了这一个问题,自信满满的说了一大堆,什么是序列化、什么是反序列化、什么场景的时候才会用到等,然后面试官说:那你能说一下序列化和反序列化底层是如何实现的吗?一脸懵逼,然后回家等通知!结果自然是凉了~
Java高级攻城狮
2019/05/04
4.1K0
序列化和反序列化的底层实现原理是什么?
带你了解Java的序列化(Serializable)与反序列化
序列化过程: 是指把一个Java对象变成二进制内容,实质上就是一个byte[]数组。 因为序列化后可以把byte[]保存到文件中,或者把byte[]通过网络传输到远程(IO),这样,就相当于把Java对象存储到文件或者通过网络传输出去了。
陈哈哈
2020/07/06
2.3K0
Java序列化和反序列化,你该知道得更多
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象——百度词条解释。
用户1615728
2019/05/07
6730
Java序列化和反序列化,你该知道得更多
Java对象的序列化(Serialization)和反序列化详解
####1.序列化和反序列化 序列化(Serialization)是将对象的状态信息转化为可以存储或者传输的形式的过程,一般将一个对象存储到一个储存媒介,例如档案或记忆体缓冲等,在网络传输过程中,可以是字节或者XML等格式;而字节或者XML格式的可以还原成完全相等的对象,这个相反的过程又称为反序列化;
全栈程序员站长
2022/07/04
8520
Java 序列化与反序列化
1、什么是序列化?为什么要序列化?     Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程。     我们都知道,在进行浏览器访问的时候,我们看到的文本、图片、音频、视频等都是通过二进制序列进行传输的,那么如果我们需要将Java对象进行传输的时候,是不是也应该先将对象进行序列化?答案是肯定的,我们需要先将Java对象进行序列化,然后通过网络,IO进行传输,当到达目的地之后,再进行反序列化获取到我们想要的对象,最后完成通信。 2、如何实现序列化 2.1、使用
九灵
2018/03/09
1.3K0
Java 对象序列化和反序列化
     之前的文章中我们介绍过有关字节流字符流的使用,当时我们对于将一个对象输出到流中的操作,使用DataOutputStream流将该对象中的每个属性值逐个输出到流中,读出时相反。在我们看来这种行
Single
2018/01/04
1K0
面试:什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决?
点击上方蓝色“程序猿DD”,选择“设为星标” 回复“资源”获取独家整理的学习资料! 作者 | riemann_ 来源 | blog.csdn.net/riemann_/article/details/87835260 遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题 什么叫序列化和反序列化 作用。为啥要实现这个 Serializable 接口,也就是为啥要序列化 serialVersionUID 这个的值到底是在怎么设置的,有什么用。有的是1L,有的是一长串数字,迷惑
程序猿DD
2023/04/04
4250
面试:什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决?
Java 序列化问题
如果不指定 serialVersionUID ,当你添加或者修改类中的任何字段时,已序列化类将无法恢复。因为新类和旧序列化对象生成的serialVersionUID 不同,序列化的过程将依赖正确的序列化对象恢复状态的。否则会报错 java.io.InvalidClassException 。
王小明_HIT
2020/03/25
5710
Java基础18:Java序列化与反序列化
本文介绍了Java序列化的基本概念,序列化和反序列化的使用方法,以及实现原理等,比较全面地总结序列化相关知识点,并且使用具体例子来加以佐证。
程序员黄小斜
2019/04/07
1.1K0
Java对象的序列化和反序列化源码阅读
前言 序列化和反序列化看起来用的不多,但用起来就很关键,因为稍一不注意就会出现问题。序列化的应用场景在哪里?当然是数据存储和传输。比如缓存,需要将对象复刻到硬盘存储,即使断电也可以重新反序列化恢复。下面简单理解序列化的用法以及注意事项。 如何序列化 Java中想要序列化一个对象,必须实现Serializable接口。然后就可以持久化和反序列化了。下面是一个简单用法。 项目测试代码: https://github.com/Ryan-Miao/someTest/blob/master/src/main/jav
Ryan-Miao
2018/03/14
1.2K0
java序列化反序列化深入探究
When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化。写一个排序算法也用不到序列化和反序列化。但是当你想要将一个对象进行持久化写入文件,或者你想将一个对象从一个网络地址通过网络协议发送到另一个网络地址时,这时候就需要考虑序列化和反序列化了。另外如果你想对一个对象实例进行深度拷贝,也可以通过序列化和反序列化的方式进行。 What---什么是序列化和反序列化: Serialization-序列化:可以看做是将一个对象转化为二进制流的过程 Deseriali
SecondWorld
2018/03/14
7320
关于序列化/反序列化,我梭哈
光看定义上,对于初学者来说,可能很难一下子理解序列化的意义,尤其是面对这种特别学术词语的时候,内心会不由自主的发问:它到底是啥,用来干嘛的?
Java极客技术
2022/12/02
4850
[填坑篇]Java序列化与反序列化注意事项与细节探究
参与序列化的引用类型也必须实现Serializable接口,否则会报NotSerializableException异常
九转成圣
2024/04/10
2610
【愚公系列】2022年01月 Java教学课程 57-对象的序列化和反序列化
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
愚公搬代码
2022/01/15
4240
【愚公系列】2022年01月 Java教学课程 57-对象的序列化和反序列化
推荐阅读
相关推荐
序列化/反序列化,我忍你很久了,淦!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验