写在开头

哈喽大家好,在高铁上码字的感觉是真不爽啊,小桌板又拥挤,旁边的小朋友也比较的吵闹,影响思绪,但这丝毫不影响咱学习的劲头!哈哈哈,在这喧哗的车厢中,思考着这样的一个问题,Java中的对象是如何在各个方法,或者网络中流转的呢?

通过这个问题便引出了我们今天的主人公:序列化与反序列化

序列化:所谓的序列化就是将Java对象或数据结构转为字节序列的过程,以便于存储到数据库、内存、文件系统或者网络传输。

反序列化:而反序列化就是序列化的逆向操作将字节流转为Java对象的过程。


序列化的基本实现(JDK)

这样一看序列化是不是非常有用?毋容置疑,这是一个无形中都会用到的知识点!那么想要在Java中实现序列化该如何做呢?继续往下看。

其实只要做到2点,就可以实现基本的序列化功能:序列流(ObjectInputStream 和 ObjectOutputStream)、实现了 Serializable 接口(一个标识型接口,没有具体的方法,仅是一种通知,告诉JVM这个对象需要序列化)

【示例代码】

/**
* 测试序列化,反序列化
* @author ConstXiong
* @date 2019-06-17 09:31:22
*/
public class TestSerializable implements Serializable { private static final long serialVersionUID = 5887391604554532906L; private int id; private String name; public TestSerializable(int id, String name) {
this.id = id;
this.name = name;
} @Override
public String toString() {
return "TestSerializable [id=" + id + ", name=" + name + "]";
} @SuppressWarnings("resource")
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("TestSerializable.obj"));
oos.writeObject("测试序列化");
oos.writeObject(618);
TestSerializable test = new TestSerializable(1, "JavaBuild");
oos.writeObject(test); //反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("TestSerializable.obj"));
System.out.println((String)ois.readObject());
System.out.println((Integer)ois.readObject());
System.out.println((TestSerializable)ois.readObject());
}
}

输出:

测试序列化
618
TestSerializable [id=1, name=JavaBuild]

这种实现方式是JDK自带的,方便好用,易于实现,代码逻辑不复杂,但它有着诸多的致命缺陷,导致很多大厂不会使用这种方式。

1、不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。

2、性能差:相比于其他序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本加大。

3、存在安全问题:序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。

序列化的其他实现方式(Kryo)

除了JDK自带的实现方式,国内外的大厂们推出过不好的开源且好用的序列化协议,比如Hessian、Kryo、Protobuf、ProtoStuff。

Hessian

一个轻量级的,自定义描述的二进制 RPC 协议。Hessian 是一个比较老的序列化实现了,并且同样也是跨语言的。Dubbo2.x 默认启用的序列化方式是 Hessian2 ,但是,Dubbo 对 Hessian2 进行了修改,不过大体结构差别不大。

Protobuf

自于 Google,性能优秀,支持多种语言,同时还是跨平台的。就是在使用中过于繁琐,因为你需要自己定义 IDL 文件和生成对应的序列化代码。这样虽然不灵活,但是,另一方面导致 protobuf 没有序列化漏洞的风险。不过后续谷歌推出了升级版,进行了很多缺陷的优化,诞生了ProtoStuff。

Kryo

目前使用最广泛,好评诸多的就是具有高性能、高效率和易于使用和扩展等特点的Kryo, 目前像Twitter、Groupon、Yahoo 以及多个著名开源项目(如 Hive、Storm)中都在使用这款序列化工具。

【示例代码】

1、引入相应的pom依赖库

<!-- 引入 Kryo 序列化工具 -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.4.0</version>
</dependency>

2、通过调用方法,通过二进制实现序列化与反序列化

public class KryoDemo {
public static void main(String[] args) throws FileNotFoundException {
Kryo kryo = new Kryo();
kryo.register(KryoParam.class); KryoParam object = new KryoParam("JavaBuild", 123); Output output = new Output(new FileOutputStream("logs/kryo.bin"));
kryo.writeObject(output, object);
output.close(); Input input = new Input(new FileInputStream("logs/kryo.bin"));
KryoParam object2 = kryo.readObject(input, KryoParam.class);
System.out.println(object2);
input.close();
}
} class KryoParam {
private String name;
private int age; public KryoParam() {
} public KryoParam(String name, int age) {
this.name = name;
this.age = 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 "KryoParam{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

序列化的细节知识点!

1、一般实现序列化接口后,还会有个serialVersionUID,它有什么作用?

答:SerialVersionUid 是为了序列化对象版本控制,告诉 JVM 各版本反序列化时是否兼容

如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常

仅增加了一个属性,希望向下兼容,老版本的数据都保留,就不用修改 删除了一个属性,或更改了类的继承关系,就不能不兼容旧数据,这时应该手动更新

SerialVersionUid

2、如果有些字段不想进行序列化怎么办?

答:对于不想进行序列化的变量,可以使用 transient 关键字修饰。transient

关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

每日一道面试题:Java中序列化与反序列化的更多相关文章

  1. Java 中序列化与反序列化

    一. 序列化和反序列化概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.将程序中的对象,放入文 ...

  2. Java 中序列化与反序列化引发的思考?

    java 中序列化指从对象转变为 二进制流的过程中需要进行序列化,而反序列化指二进制流转换为java 对象.那么有的时候java 存储到数据库不需要序列化, 而计算机系统本质存储的就是二进制文件,数据 ...

  3. JAVA中序列化和反序列化

    一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失(java回收机制)但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运 ...

  4. JAVA中序列化和反序列化中的静态成员问题

    关于这个标题的内容是面试笔试中比较常见的考题,大家跟随我的博客一起来学习下这个过程. ? ? JAVA中的序列化和反序列化主要用于: (1)将对象或者异常等写入文件,通过文件交互传输信息: (2)将对 ...

  5. “每日一道面试题”.Net中GC的运行机制

    GC 也就是垃圾回收,经常遇到的面试题,关于GC 感觉可以写一本书,我们要做的也就是简单理解,如果有意愿,可以深入研究 所谓的垃圾回收,也就是清理回收托管堆上不再被使用的对象内存,并且移动仍在被使用的 ...

  6. “每日一道面试题”.Net中所有类的基类是以及包含的方法

    闲来无事,每日一贴.水平有限,大牛勿喷. .Net中所有内建类型的基类是System.Object毋庸置疑 Puclic Class A{}和 Public Class A:System.Object ...

  7. java 对象序列化与反序列化

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

  8. Java对象序列化和反序列化的工具方法

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...

  9. Java之序列化和反序列化

    序列化的对象: package test_demo.SerializableOper; import java.io.Serializable; /* * 序列化对象需要实现序列号接口 * */ pu ...

  10. Java基础—序列化与反序列化(转载)

    转载自: Java序列化与反序列化 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化 ...

随机推荐

  1. Sublime Json 格式化

    Ctrl+Shift+P 安装  pretty json  Ctrl+Alt+J

  2. 🔥 DeepVideo 智能视频生产训练营火热报名中!

    阿里云视频云和阿里云开发者学堂联合打造 国内首个视频云训练营11月8日启幕 四天直播,技术大咖亲临授课干货 全面介绍视频智能生产技术和产品 帮助开发者迅速入门视频云 已超千人报名,丰富打卡玩法礼品 活 ...

  3. Python | BitMap算法及其实现

    BitMap概述 本文介绍 BitMap 算法的应用背景,算法思想和相关实现细节. 概括而言,BitMap 主要用来解决海量数据中元素查询,去重.以及排序等问题.这里对海量数据场景的强调,似乎暗示了这 ...

  4. L2-026 小字辈 (25 point(s)) (BFS)

    补题链接:Here 本题给定一个庞大家族的家谱,要请你给出最小一辈的名单. 输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) -- 简单起见,我们把家族成员从 1 到 ...

  5. 制作PE工具箱

    事前准备: 能上网的电脑 x1 台 大于8G的U盘 x一个(如果需要储存安装镜像的话,如果不需要的话大于1G即可) 一.下载PE工具箱 推荐使用WEPE工具箱,无广告无推广.不推荐老X桃,大X菜,大X ...

  6. vue 状态管理 一、状态管理概念和基本结构

    系列导航 vue 状态管理 一.状态管理概念和基本结构 vue 状态管理 二.状态管理的基本使用 vue 状态管理 三.Mutations和Getters用法 vue 状态管理 四.Action用法 ...

  7. Liunx常用操作(11)-VI编辑器-末行模式命令

    vI编辑器三种模式 分别为命令模式.输入模式.末行模式.

  8. 问题--QT只有全屏的时候才能使用

    1.问题 安装的版本是3.8.0,只有在全屏的时候在编辑界面不会卡,其余情况会直接卡死在这. 2.解决方式 安装了较低版本的3.14.2,解决了上述问题

  9. javaweb 项目!号 解决方案

    1:右击项目工程名称2:Properties3:  Jvav Build Path4:  Libraries5:  Add External JARS6:  找到"E:\apache-tom ...

  10. [转帖]/dev/random 和 /dev/urandom的一点备忘

    https://www.cnblogs.com/ohmygirl/p/random.html 1.  基本介绍 /dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两 ...