想象一下,你刚开始玩一个游戏,一进游戏,首先系统提示你需要创建一个角色。
新建角色对象:姓名(宇宙第一无敌厉害)谁会取这样的名字哈哈哈、性别、门派、等级......
建完角色之后,来到新手村,对于一个心怀大侠梦的有志青年当然不能被困在这小小的新手村了,所以你需要去刷boss
攒经验升级。
boss
对象:血量、等级、拥有技能......
就这样,经过不懈努力,你终于达到了能出新手村的等级。这时候,夜深了,你妈气急败坏叫你关电脑睡觉。大家都知道,创建的对象是保存在内存中的,内存中的数据断电即失。难道刚要出新手村,大侠梦就破灭了?怎么办呢?
二、大侠梦持续输出——序列化
为了不让无数青年的大侠梦关机即碎,序列化技术出现了,在游戏中的体现就是存档。即,在退出游戏的时候,点击存档按钮,这时候,你游戏角色的等级,装备等都会被保存在存储媒体中(硬盘等)。这时候,就算你关机了,下次再次登录游戏,还是你关机时保存的角色状态。
总结:序列化就是将内存中的对象数据存储到存储媒体中。
三、小爷我又回来了——反序列化
当天晚上,你在你妈的压迫下无奈关机睡觉了。第二天起来你迫不及待打开游戏准备再次大干一场,可是游戏角色已经被序列化到硬盘中,怎么取出来呢?这时候,反序列化技术就出现了。就是把你存在硬盘上的数据还原成原来的游戏对象,该是多少级还是多少级,该是啥装备就是啥装备。
总结:反序列化就是将存储在媒体中的对象还原成内存中对象。
序列化与反序列化扩展:
对于序列化来讲,不单单是作为将内存中的数据存储到媒体中,其网络传输也是一大作用。
你想想,玩游戏当然是大家一起玩才好了。每个游戏玩家在游戏世界中都可以进行沟通交流,当你刷boss
的时候,爆到了一把一刀999的屠龙宝刀。这时候,你可以选择高价卖给游戏的其他土豪玩家。这时候,你不可能直接通过网线把这个给人家,而是通过序列化的方法,把这把屠龙刀传输给买家,买家在接收到这个数据之后,再通过反序列化将这把宝刀还原。
即,序列化的作用:
存储内存中的对象、进行网络传输。
四、序列化机制探究
上文说到,序列化可以进行网络传输,说到网络传输,那么I/O
就不能陌生了,I/O
传输支持的数据格式是字节数组。即,要想进行网络传输,就是将传输的对象转换成字节数组。但是,我们不能盲目随便转换成字节数组,因为你后面还需要将对象进行还原。也就是说,在进行转换的时候你要指定一个规则(序列化),在将对象转换成字节数组的时候按照这个规则进行转换。那个将对象进行还原的时候,按照规则(反序列化)进行还原。你不能将一个人偶拆了之后,装的时候,把手装成脚。
即,序列化机制:
将对象转换成字节数组的时候的转换规则,这种转换规则就是序列化机制。
五、序列化的种类
原生的JDK
JDK
自带了序列化方法,只需要实现了Serializable
接口的类,就可以通过ObjectOutputStream
类将对象变成byte[]字节数组。
弊端:只能java
自己玩。
代码示例:
/** * @ClassName Student * @Description Student类对象 * @Author LH * @Date 2022/6/12 10:32 */ @Data public class Student implements Serializable { private String id; private String name; private int age; }
/** * @ClassName JDKSerialize * @Description JDK序列化接口测试 * @Author LH * @Date 2022/6/12 10:41 */ public class JDKSerialize { /** * 对象序列化 * @param student 学生对象 * @throws IOException 抛出io异常 */ public static void serializeStudent(Student student) throws IOException { ObjectOutputStream oo = new ObjectOutputStream(new ObjectOutputStream(Files.newOutputStream(new File("E:/java/workplace/study/student.txt").toPath()))); oo.writeObject(student); oo.close(); } /** * 对象反序列化 * @param path 反序列化文件路径 * @return Student 还原的学生对象 * @throws IOException 抛出io异常 * @throws ClassNotFoundException 找不到文件异常 */ public static Student deSerializeStudent(String path) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new ObjectInputStream(Files.newInputStream(new File(path).toPath()))); Student student = (Student) ois.readObject(); ois.close(); return student; } public static void main(String[] args) { // 创建一个student对象 Student student = new Student(); student.setId("1"); student.setName("LH"); student.setAge(17); try { // 序列化student对象 JDKSerialize.serializeStudent(student); // student对象饭序列化 String path = "E:/java/workplace/study/student.txt"; Student deSerializeStudent = JDKSerialize.deSerializeStudent(path); System.out.println("student id:" + deSerializeStudent.getId() + "student age:" + deSerializeStudent.getAge() + "student name:" + deSerializeStudent.getName()); } catch (Exception e) { e.printStackTrace(); } } }
ProtoBuf
谷歌推出,一种语言无关、平台无关、可扩展的序列化结构数据的方法,可用于通信协议、数据存储等。序列化后体积小,一般用于对传输性能有较高要求的系统。
了解不是很多,后面工作用到的话再来进行扩展。
JSON
在系统之间进行交互的时候很常用。
JSON
序列化方式生成的是一串有规则的字符串,可读性强。是有规则的字符串,不跟任何编程语言绑定,天然上就具备了跨平台。
弊端:体积大。
常见的工具有:
fastJSON
、Jackson
、Gson
等。工作中比较常用的就是阿里的fastJSON,使用起来也很简单,直接调用转换的api即可,了解更多可以去官网看看。
各种序列化手段都有不同的特性,看你的业务再去选型。
序列化如何选择
主要考虑三点:
-
选择的序列化手段是否需要跨平台
-
选择的序列化手段的速度要求
-