序列化和反序列化的概念
把對象轉換為字節序列的過程稱為對象的序列化。
把字節序列恢復為對象的過程稱為對象的反序列化。
對象的序列化主要有兩種用途:
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);
測試結果:
示例源碼地址: