#1.序列化与反序列化的概念
将对象转换为字节序列的过程称为对象的序列化。
反过来,将字节序列恢复成对象的过程称为对象的反序列化。
#2.为何要将对象序列化?
2.1当咱们须要将内存中的对象保存到一个文件中/数据库中的时候
一般咱们须要将某些对象进行序列化,让它离开内存空间,入驻物理硬盘,以便长期保存,须要的时候在调取它。例如:缓存,咱们须要将缓存存储起来,须要的时候再将它取出来。
2.2须要在网络上传送对象的时候
当两个进程在进行远程通讯时,彼此时间须要发送数据,不管哪一种类型的数据,都会以二进制序列的形式在网络上传送。
#3.如何实现对象序列化?
很简单,将须要序列化的类实现Serializable接口便可,Serializable接口中没有任何方法。将它理解为一个标记,即代表这个类能够序列化。
#4.实现序列化原理
java.io.ObjectOutputStream表示对象输出流,writeObject(Object obj)方法将指定对象obj写入一个输出流中,即对该对象进行序列化。
java.io.ObjectInputStream表示对象输入流,readObject()方法从ObjectInputStream读取字节序列,再将它们反序列化成为一个对象,并将其返回。
只有实现了Serializable接口的类才能被序列化。对象序列化步骤:
1>建立一个对象输出流,即ObjectOutputStream,它能够包装一个目标输出流,例如文件输出流。
2>调用writeObject(Object obj)方法,参数为obj
对象反序列化过程:
1>建立一个对象输入流,即ObjectInputStream,它能够包装一个源输入流,例如文件输入流。
2>调用readObject()方法读取对象
#5.实例
5.1 定义一个User类并实现Serializablejava
public class User implements Serializable{ //序列化id private static final long serialVersionUID = 1L; private Integer id; private String name; }
5.2序列化与反序列化User对象spring
public class TestSerializable { public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { //序列化对象 SerializeUser(); //反序列化 User user = DeSerializeUser(); System.out.println(user); } }
序列化对象代码数据库
/** * 序列化User对象 * 1>建立一个对象输出流,即ObjectOutputStream,它能够包装一个目标输出流,例如文件输出流。 * 2>调用writeObject(Object obj)方法,参数为obj * @throws IllegalAccessException * @throws InstantiationException */ private static void SerializeUser() throws InstantiationException, IllegalAccessException{ //运用反射建立User对象 User user = new User(); try { Class<?> clazz = Class.forName("com.test.spring.bean.User"); user = (User) clazz.newInstance(); user.setId(1001); user.setName("张三"); } catch (ClassNotFoundException e1) { System.out.println("没有找到该类"); e1.printStackTrace(); } //建立对象输出流 //将User对象序列化,并存储到E盘的Test文件下User.txt文件中 ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\Test\\User.txt"))); oos.writeObject(user); System.out.println("对象序列化成功"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } }
反序列化代码缓存
/** * 反序列化User对象 * 1>建立一个对象输入流,即ObjectInputStream,它能够包装一个源输入流,例如文件输入流。 * 2>调用readObject()方法读取对象 * @throws ClassNotFoundException */ private static User DeSerializeUser() throws ClassNotFoundException{ //new方式建立对象 User user = new User(); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(new File("E:\\Test\\User.txt"))); user = (User) ois.readObject(); System.out.println("对象反序列化成功"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { try { ois.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return user; }
#6.serialVersionUID
serialVersionUID是序列化版本号,全部实现Serializable接口的类都须要有一个表示序列化版本标识符。
那这个serialVersionUID有什么用呢?
1.咱们去掉User类中的serialVersionUID
2.在序列化这个类
3.在User类中添加新的属性
4.再反序列化User类
报错信息以下网络
java.io.InvalidClassException: com.test.spring.bean.User; local class incompatible: stream classdesc serialVersionUID = 5057804141597769629, local class serialVersionUID = -2824417979782532292
反序列化的过程当中出现问题,报错是stream classdesc serialVersionUID与local class serialVersionUID不一致。
在User类中,若是咱们没有指定serialVersionUID,则java编译器会自动给该类添加一个serialVersionUID;因为没有显式的指定serialVersionUID,全部咱们修改了User类以后,编译器又会给咱们指定一个serialVersionUID,这就出现了两个序列化版本号不一致的错误。
接着测试下有serialVersionUID的状况
1.加上serialVersionUID
2.序列化对象
3.修改对象字段
4.直接反序列化对象
测试了(假设新增属性为age),证实能够反序列化成功,结果以下测试
对象反序列化成功 User [id=1001, name=张三, age=null]