官术网_书友最值得收藏!

2.7 序列化

Java對象在JVM運行時被創建、更新和銷毀,當JVM退出時,對象也會隨之銷毀,即這些對象的生命周期不會比JVM的生命周期更長。但在現實應用中,我們常常需要將對象及其狀態在多個應用之間傳遞、共享,或者將對象及其狀態持久化,在其他地方重新讀取被保存的對象及其狀態繼續進行處理。這就需要通過將Java對象序列化來實現。

在使用Java序列化技術保存對象及其狀態信息時,對象及其狀態信息會被保存在一組字節數組中,在需要時再將這些字節數組反序列化為對象。注意,對象序列化保存的是對象的狀態,即它的成員變量,因此類中的靜態變量不會被序列化。

對象序列化除了用于持久化對象,在RPC(遠程過程調用)或者網絡傳輸中也經常被使用。

2.7.1 Java序列化API的使用

Java序列化API為處理對象序列化提供了一個標準機制,具體的Java系列化需要注意以下事項。

◎ 類要實現序列化功能,只需實現java.io.Serializable接口即可。

◎ 序列化和反序列化必須保持序列化的ID一致,一般使用private static final long serialVersionUID定義序列化ID。

◎ 序列化并不保存靜態變量。

◎ 在需要序列化父類變量時,父類也需要實現Serializable接口。

◎ 使用Transient關鍵字可以阻止該變量被序列化,在被反序列化后,transient變量的值被設為對應類型的初始值,例如,int類型變量的值是0,對象類型變量的值是null。

具體的序列化實現代碼如下:

import  java.io.Serializable;
//通過實現Serializable接口定義可序列化的Worker類
public  class  Wroker  implements  Serializable  {
    //定義序列化的ID
    private  static  final  long  serialVersionUID  =  123456789L;
    //name屬性將被序列化
    private  String  name;
    //transient修飾的變量不會被序列化
    private  transient   int  salary;
    //靜態變量屬于類信息,不屬于對象的狀態,因此不會被序列化
    static  int  age  =100;
    public  String  getName()  {
      return  name;
    }
    public  void  setName(String  name)  {
      this.name  =  name;
    }
}

以上代碼通過implements Serializable實現了一個序列化的類。注意,transient修飾的屬性和static修飾的靜態屬性不會被序列化。

對象通過序列化后在網絡上傳輸時,基于網絡安全,我們可以在序列化前將一些敏感字段(用戶名、密碼、身份證號碼)使用秘鑰進行加密,在反序列化后再基于秘鑰對數據進行解密。這樣即使數據在網絡中被劫持,由于缺少秘鑰也無法對數據進行解析,這樣可以在一定程度上保證序列化對象的數據安全。

2.7.2 序列化和反序列化

在Java生態中有很多優秀的序列化框架,比如arvo、protobuf、thrift、fastjson。我們也可以基于JDK原生的ObjectOutputStream和ObjectInputStream類實現對象進行序列化及反序列化,并調用其writeObject和readObject方法實現自定義序列化策略。具體的實現代碼如下:

public  static  void  main(String[]  args)  throws  Exception  {
    //序列化數據到磁盤
    FileOutputStream  fos  =  new  FileOutputStream("worker.out");
    ObjectOutputStream  oos  =  new  ObjectOutputStream(fos);
    Wroker  testObject  =  new  Wroker();
    testObject.setName("alex");
    oos.writeObject(testObject);
    oos.flush();
    oos.close();
    //反序列化磁盤數據并解析數據狀態
    FileInputStream  fis  =  new  FileInputStream("worker.out");
    ObjectInputStream  ois  =  new  ObjectInputStream(fis);
    Wroker  deTest  =  (Wroker)  ois.readObject();
    System.out.println(deTest.getName());
 }

以上代碼通過文件流的方式將wroker對象的狀態寫入磁盤中,在需要使用的時候再以文件流的方式將其讀取并反序列化成我們需要的對象及其狀態數據。

主站蜘蛛池模板: 长宁县| 乌兰浩特市| 安仁县| 新安县| 阳西县| 剑河县| 渝中区| 瑞安市| 师宗县| 南昌市| 富源县| 柏乡县| 壶关县| 雷山县| 逊克县| 绥江县| 玉屏| 博客| 麟游县| 敖汉旗| 五常市| 湟中县| 容城县| 兴仁县| 沽源县| 灵台县| 东丰县| 马公市| 宜昌市| 兴安盟| 大厂| 崇州市| 平湖市| 永定县| 大英县| 睢宁县| 桦甸市| 双牌县| 通道| 尚志市| 大邑县|