序列化与反序列化

面对序列化与反序列化,很多人问我这个问题,是什么?用来做什么?趁着空闲,打算记录一下。
  1、序列化与反序列化的概念:
序列化:把对象转换为字节序列的过程叫做对象的序列化。
反序列化:把字节序列回复为对象的过程称为对象的反序列化。
 
通常在代码运行的时候可以看到好多对象,而这些对象想要保存起来,比如说redis存储Map对象,那么redis中存储的这个对象是以序列化的形式保存起来,当我们需要用的时候,从redis取出,把这些字节存储的内容转成原来的对象进行展示。
 
2、什么情况下需要序列化
 当你想把呢村的对象状态保存到某一个文件中或者数据库中【redis相当于一个数据库】
当你想用套接字在网络上传达对象的时候;
当你想通过RMI传输对象的时候;
【以上几种方式我大部分用的都是redis存对象的时候用到过】
 
3、如何实现序列化
实现Serializable接口
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
 
/**
* @author :biejie
* @date :Created in 2019/1/9 17:14
* @description:理解序列化与反序列化含义
* @modified By:
* @version: 1.0$
*/
public class OneController {
public static void main(String[] args) throws Exception {
serializeFlyPig();
Map<String,Object> TestOne = deserializeFlyPig();
System.out.println(TestOne.toString());
 
}
 
/**
* 序列化
*/
private static void serializeFlyPig() throws IOException {
Map<String,Object> map =new HashMap<>();
map.put("a","a");
map.put("fds","感觉");
map.put("584","放大");
 
// ObjectOutputStream 对象输出流,将 testOne 对象存储到d盘的 testOne.txt 文件中,完成对 testOne 对象的序列化操作
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/testOne.txt")));
oos.writeObject(map);
System.out.println("testOne 对象序列化成功!");
oos.close();
}
 
/**
* 反序列化
*/
private static Map<String,Object> deserializeFlyPig() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/testOne.txt")));
Map<String,Object> person = (Map<String, Object>) ois.readObject();
System.out.println("testOne 对象反序列化成功!");
return person;
}
 
 
 
}
 
 
输出结果如下:
 

 

文本打印内容:
 

 

 
对于上述序列化与反序列化的代码解读:
ObjectOutputStream:对象输出流
ObjectOutputStream.writeObject(Object obj):可对参数指定的obj对象进行序列化,然后把得到的字节序列写到一个目标输出流中。
ObjectInputStream:对象输入流
ObjectInputStream.readObject():从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
 
不要以为这样就掌握了序列化,
实体类继承 java.io.Serializable后,需要设置序列化ID,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。
通俗意义上面的讲就是有一个 序列号id:serialVersionUID ,默认java会根据class计算 serialVersionUID值,它的作用是用在反序列化【检查】当前类是否被修改过,如果发现 serialVersionUID与当前对不上号,就会报异常, 那么会抛出 java.io.InvalidClassException的异常,这种情况发生在由于种种因素修改了序列化对象的类文件时。 有时候我们确实有这样的需求,我对类进行改变,但又希望反序列化的时候还是与之前版本的序列化的对象类的 serialVersionUID进行对应,那么我们只需要指定 serialVersionUID的值为某个固定值就可以了 .
看到这,我尝试了一下,发现:

 

我先序列化一个有5个key-value对象,并且把字节序列存到另一个地方,

 

然后我再序列化一个有3个key-value对象,

 

然后我把test3复制到testOne文本内,然后放反序列化字段:

 

执行;
 

 

发现报上面的错误,瞬间感觉自己弱弱的,怎么和自己的预期不是一样的,然后找了相关资料,才知道这个问题是 
意思是用ObjectInputStream反序列化读入的数据不是由ObjectOutputStream产生的。
 
然后我遇到了困惑,上网试了几个方法解决,都没得用,还需要众神解惑下。

转载于:https://www.cnblogs.com/lyting/p/10362429.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值