更宽泛的序列化概念
在通信模型中,序列化和反序列化属于通讯协议的一部分
OSI 七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象 -- 这两个功能就是序列化和反序列化
四层 TCP/IP 协议的应用层对应与 OSI 七层协议模型的应用层,展示层和会话层;所以序列化协议属于 TCP/IP 协议应用层的一部分
定义
序列化: 将数据结构或对象转换成二进制串的过程。
反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
但是生成二进制流的方案却千差万别,相同的对象使用不同序列化方案生成的二进制流也是不同的
不同的计算机语言中,数据结构,对象以及二进制串的表示方式并不相同
在 Java 语言中最接近数据结构的概念,就是 POJO(Plain Old Java Object)或者 Javabean
C语言中的二进制串:序列化所生成的二进制串指的是存储在内存中的一块数据。C 语言的字符串可以直接被传输层使用,因为其本质上就是以'0'结尾的存储在内存中的二进制串
二进制串在 Java 里面所指的是 byte[],byte 是 Java 的 8 中原生数据类型之一(Primitive data types)
java对象JDK 序列化
(1)内存中对象
User user = new User();
user.setName("jack");
user.setOld(18);
(2)对象序列化到磁盘
fos = new FileOutputStream("userJava.serialize");
objOutStream = new ObjectOutputStream(fos);
objOutStream.writeObject(user);
(3)磁盘反序列化到内存
fis = new FileInputStream("userJava.serialize");
objInStream = new ObjectInputStream(fis);
User user2 = (User) objInStream.readObject();
java对象序列化后,写到文件磁盘上,使用二进制文件打开如下:
事实上序列文件是一个二进制文件byte[],右侧是可以看出的部分二进制翻译;文件中含有类名全称、属性类型、属性值等、serialVersionUID等,利用这些信息,反序列化时就可以在内存中创建一个新的一个属性值一样的对象(反序列化过程中存在一样的User类,否则在反序列化时会报出ClassNotFoundException异常)
注意:(1)序列化没有生成与方法相关的信息,只有与属性相关的(2)static和transient修饰的属性不会被序列化
JSON格式字符串序列化
首先,java中String和二进制串是两个概念,String是一个对象
对象 -> json格式的字符串 -> 二进制流 (在网络中传输)-> 二进制流 -> json格式的字符串 -> 对象
对象转换成json格式字符串时候,不涉及字符集问题,即将对象转换为满足json格式规范的String对象:{"xxx":"yyy"}
String类型再转为为二进制流时,本人推测调用 byte[] getBytes(charsetName) 方法
如上面所述:从json格式字符串转为二进制流在网络中传输的时候,就会涉及到字符集问题了(不同字符集会转换成不同的二进制序列),如http响应,会把响应体指定为utf-8形式;
再如将json格式的字符串保存到文件,如果含有中文内容:
String content = {"name":"梅西"}
File file = new File("content.txt");
FileOutputStream fileWriter = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fileWriter,"ASCII");
osw.write(content);
打开txt文件就变成这样:
{"name":"??"}
String 对象使用JDK序列化,也会生成和String类相关的很多信息
所以使用原生JDK序列化生成二进制流和使用String.getBytes(charsetName)生成出的二进制字节流是不同的