目录

  • 序列化示例
  • 有父类的对象序列化
  • Serializable和Externalizable区别
  • 序列化和反序列化实现
  • serialVersionUID不一致有什么问题
    • 1、先注释掉反序列化代码, 执行序列化代码, 然后User类新增一个属性sex
    • 2、再注释掉序列化代码执行反序列化代码
    • 3、指定serialVersionUID
  • 序列化字段修饰
  • static属性为什么不会被序列化?
  • serialVersionUID也被static修饰, 为什么serialVersionUID会被序列化?
  • 小结


相关阅读:
什么是序列化

序列化示例

String类型序列化的源码示例:

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];/** Cache the hash code for the string */private int hash; // Default to 0/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L;private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];public String() {this.value = "".value;}
...
}

String类型实现了Serializable接口, 并显示指定serialVersionUID的值.

对象持久化到数据库示例:

<insert id="insertUser" parameterType="xxx.User">  INSERT INTO user(name, age) VALUES (#{name}, #{age})
</insert>

实际上我们并不是将整个对象持久化到数据库中, 而是将对象中的属性持久化到数据库中, 而这些属性都是实现了Serializable接口的基本属性。

有父类的对象序列化

在Java中,如果对象的类或父类实现了Serializable接口或Externalizable接口,则称该对象可序列化。

有继承的对象序列化有如下三种情况:

  1. 如果父类可序列化,则子类可自动序列化
  2. 即使父类不可序列化,子类仍可以序列化
  3. 如果我们希望子类不被序列化,即使父类是可序列化的

类可序列化时,子类自动变为可序列化示例:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;class Parent implements Serializable {String name = "三省同学";
}class Child extends Parent {String name1 = "sxtx";
}/*** 父类序列化,子类自动序列化示例** @Author sxtx*/
public class SerializableExample {public static void main(String[] args) throws IOException, ClassNotFoundException {Child writer = new Child();FileOutputStream fos = new FileOutputStream("file.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(writer);FileInputStream fis = new FileInputStream("file.txt");ObjectInputStream ois = new ObjectInputStream(fis);Child reader = (Child) ois.readObject();System.out.println(reader.name + "," + reader.name1);}
}

输出:

三省同学,sxtx

Serializable和Externalizable区别

1、Serializable序列化时不会调用默认的构造器,而Externalizable序列化时会调用默认构造器的。
2、Serializable:一个对象想要被序列化,那么它的类就要实现此接口,这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。
3、Externalizable:他是Serializable接口的子类,有时我们不希望序列化那么多,可以使用这个接口,这个接口的writeExternal()和readExternal()方法可以指定序列化哪些属性。

序列化和反序列化实现

三种实现方式如下:

1、若User类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化。

ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。
ObjcetInputStream采用默认的反序列化方式,对User对象的非transient的实例变量进行反序列化。

2、若User类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。

ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。

ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

3、若User类实现了Externalnalizable接口,且User类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。

ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。
ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化。

代码示例:

@Data
public class User implements Serializable {private String name;  private Integer age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

先进行序列化, 再进行反序列化.

 public static void main(String[] args) throws Exception {User user = new User();  user.setName("三省同学");user.setAge(18);  System.out.println("序列化前的结果: " + user);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:\\file.txt")));oos.writeObject(user);oos.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:\\file.txt")));User dUser = (User) ois.readObject();System.out.println("反序列化后的结果: "+ dUser);}

结果:

序列化前的结果: User{name='三省同学', age=18}
反序列化后的结果: User{name='三省同学', age=18}

serialVersionUID不一致有什么问题

1、先注释掉反序列化代码, 执行序列化代码, 然后User类新增一个属性sex

@Data
public class User implements Serializable {private String name;  private Integer age;private String sex;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}
}

2、再注释掉序列化代码执行反序列化代码

最后结果如下:


序列化前的结果: User{name='三省同学', age=18}Exception in thread "main" java.io.InvalidClassException: xxx.User; local class incompatible: stream classdesc serialVersionUID = -5701321611009304438, local class serialVersionUID = 1670957499376994577at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)at xxx.SerializableTest.main(SerializableTest.java:18)

报错结果为序列化与反序列化产生的serialVersionUID不一致.

3、指定serialVersionUID

private static final long serialVersionUID = 1L;

再执行上述步骤, 结果如下:

序列化前的结果: User{name='tyshawn', age=18}
反序列化后的结果: User{name='tyshawn', age=18, sex='null'}

指定serialVersionUID可解决了序列化与反序列化产生的serialVersionUID不一致的问题.

序列化字段修饰

被transient关键字修饰的属性不会被序列化, static属性也不会被序列化.

static属性为什么不会被序列化?

因为序列化是针对对象而言的, 而static属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.

serialVersionUID也被static修饰, 为什么serialVersionUID会被序列化?

其实serialVersionUID属性并没有被序列化, JVM在序列化对象时会自动生成一个serialVersionUID, 然后将我们显示指定的serialVersionUID属性值赋给自动生成的serialVersionUID.

小结

1、序列化时,只对对象的状态进行保存,而不管对象的方法;
2、当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
3、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
4、并非所有的对象都可以序列化,比如:

安全方面的原因:
如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;

资源分配方面的原因:
比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现;

5、声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

6、序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:

在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;

在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

7、Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;

8、如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因;

点赞 收藏 关注
三月春花渐次醒,迢迢年华谁老去

一文了解Java序列化与反序列化相关推荐

  1. java序列化和反序列化_Java恶意序列化背后的历史和动机

    java序列化和反序列化 与Java的序列化机制相关的问题已广为人知. 有效的Java 1st Edition (第10章)和有效的Java 2nd Edition (第11章)的整个最后一章都专门讨 ...

  2. Serializable详解(1):代码验证Java序列化与反序列化

    说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...

  3. java 序列化概念和作用_结合代码详细解读Java序列化与反序列化概念理解

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  4. Java中如何引用另一个类里的集合_【18期】Java序列化与反序列化三连问:是什么?为什么要?如何做?...

    Java序列化与反序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: 序列化:对象序列化的最主要的用处就是在传递和保存对象 ...

  5. java序列化与反序列化(转)

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  6. java序列化和反序列化以及序列化ID的作用分析

     java序列化和反序列化 一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一 ...

  7. 教你彻底学会Java序列化和反序列化

    Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件以后,在内存中重构对象 ...

  8. 理论 | 教你彻底学会Java序列化和反序列化

    这是小小本周的第四篇 Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程.反序列化:客户端重文件,或者网络中获取到文件 ...

  9. Java序列化与反序列化(一)

    目录 序列化与反序列化 1.最简单的使用:Serializable 接口 2. 序列化 ID 的问题 3. 静态字段不会序列化 4. 屏蔽字段:transient 5. 父类的序列化 6. 自定义序列 ...

最新文章

  1. MySQL数据库(五)使用pymysql对数据库进行增删改查
  2. Python培训班线上线下哪种靠谱
  3. Web前端开发人员和设计师必读文章推荐【系列九】
  4. Windows环境下的NodeJS+NPM+Bower安装配置
  5. 操作系统,看这一篇足够了!
  6. 冷板式液冷--术语、定义和缩略语(6-1)
  7. win7+eclipse用maven构建hadoop项目注意事项
  8. Python3.7模块之hashlib
  9. 《大数据》2015年第3期“网络大数据专题”——大数据时代的互联网分析引擎...
  10. 用VC写Assembly代码(2)
  11. qt 创建文件_xmake从入门到精通2:创建和编译工程
  12. ebm风扇选型手册_EBM风扇选择方法
  13. 【Elasticsearch】运行 400 多个节点的 Elasticsearch 集群
  14. bat中的[%~dp0]使用
  15. Leetcode 刷题笔记(二十五) ——动态规划篇之背包问题:完全背包
  16. 如何做好网站SEO,和大家分享十年草根站长优化成绩
  17. Springboot创建webService接口时的cxfconfi文件报错出现DispatcherServletPath不能找到
  18. 详解DNS域名解析全过程
  19. 一个例子搞懂条件概率、先验概率、后验概率、全概率公式和贝叶斯公式
  20. C++生成0到1之间的随机数

热门文章

  1. 侵犯公民个人信息: “两高”首次出台司法解释 打击大数据征信乱象
  2. 中考不能用计算机ka,中考电脑阅卷“内幕”,你的孩子都注意到了吗?
  3. 暗暗暗暗啊暗暗暗暗啊
  4. Modem2G/3G/4G/5G:解决TDS-CDMA:HSDPA:能注册上call box,但无法连接(Integrity protection not activated)
  5. 物联网--思科模拟器--室内家用电器控制
  6. Clion配置导致中文乱码问题 char长度限制导致中文乱码问题
  7. AI测温落地趋势:已成日常刚需 产品形态呈细分化发展
  8. 常见的粒子动画js特效代码particles.js
  9. Win11打不开exe应用程序怎么办?Win11无法打开exe程序解决方法
  10. Esko ArtiosCAD v14.1 ALPHA Biuld 1132 1DVD结构设计