序列化和反序列化的概念
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
JDK类库中的序列化API
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,
而仅实现Serializable接口的类可以 采用默认的序列化方式 。
对象序列化包括如下步骤:
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
2) 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
2) 通过对象输入流的readObject()方法读取对象。
示例:
新建一个Car 类
1 package com.oukele.redis2.entity; 2 3 import java.io.Serializable; 4 5 public class Car implements Serializable { 6 7 /* 8 * 编号 9 */ 10 private int id; 11 /* 12 * 车名 13 */ 14 private String name; 15 /* 16 * 车速 17 */ 18 private double speed; 19 20 public Car(String name,double speed ){ 21 this.name = name; 22 this.speed = speed; 23 } 24 25 public Car(int id, String name, double speed) { 26 this.id = id; 27 this.name = name; 28 this.speed = speed; 29 } 30 31 public int getId() { 32 return id; 33 } 34 35 public void setId(int id) { 36 this.id = id; 37 } 38 39 public String getName() { 40 return name; 41 } 42 43 public void setName(String name) { 44 this.name = name; 45 } 46 47 public double getSpeed() { 48 return speed; 49 } 50 51 public void setSpeed(double speed) { 52 this.speed = speed; 53 } 54 55 @Override 56 public String toString() { 57 return "Car{" + 58 "id=" + id + 59 ", name='" + name + '\'' + 60 ", speed=" + speed + 61 '}'; 62 } 63 }
新建一个 SerializeUtil 类 (封装 序列化 和 反序列化 的方法,便于调用 )
1 package com.oukele.redis2.util; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 8 public class SerializeUtil { 9 10 /* 11 * 序列化 12 * */ 13 public static byte[] serialize(Object object){ 14 //序列化流 (输出流) --> 表示向一个目标 写入数据 15 ObjectOutputStream objectOutputStream =null; 16 //字节数组输出流 17 ByteArrayOutputStream byteArrayOutputStream = null; 18 try{ 19 //创建一个缓冲区 20 byteArrayOutputStream = new ByteArrayOutputStream(); 21 //将 对象 序列化成 字节后 输入缓冲区中 22 objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 23 //序列化 对象 24 objectOutputStream.writeObject(object); 25 //得 到 序列化字节 26 byte[] bytes = byteArrayOutputStream.toByteArray(); 27 28 //清空输出流 29 objectOutputStream.flush(); 30 //释放资源 31 objectOutputStream.close(); 32 33 return bytes; 34 }catch (Exception e){ 35 System.out.println("出现异常:"+e.getMessage()); 36 } 37 return null; 38 } 39 40 /* 41 * 反序列化 42 * */ 43 44 public static <T> T deserialize(byte[] bytes,Class<T> clazz){ 45 //字节数组 46 ByteArrayInputStream byteArrayInputStream = null; 47 try{ 48 //将 得到的序列化字节 丢进 缓冲区 49 byteArrayInputStream = new ByteArrayInputStream(bytes); 50 //反序列化流 (输入流)--> 表示着从 一个 源头 读取 数据 , (读取 缓冲区中 的字节) 51 ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); 52 //反序化成 一个对象 53 return (T)objectInputStream.readObject(); 54 }catch (Exception e){ 55 System.out.println("出现异常:"+e.getMessage()); 56 } 57 return null; 58 } 59 60 61 }
测试:
1 //序列化一个对象 2 byte[] serialize = SerializeUitl.serialize(new Car(2,"宝马",88.8)); 3 //反序列化 4 Car deserialize = SerializeUitl.deserialize(serialize, Car.class); 5 System.out.println(deserialize);
测试结果:
示例源码地址: