【技術累積】【點】【java】【21】序列化二三事

基礎概念

  • 把對象等轉爲二進制進行傳輸的是序列化,反之爲反序列化;
  • 應用場景通常爲讀寫文件,傳輸數據/接口調用;

Externalizable和Serializable

java的序列化方式有兩種;html

Serializable是經常使用的方法,實現方法爲java

class User implements Serializable {
        private static final long serialVersionUID = -3226152074589523662L;
       ...
    }

實現接口,而且最好有序列化ID;ide

Externalizable是Serializable的子類,但不會自動化序列化,須要調用方法實現序列化;函數

idea自動生成序列化ID

打開設置中的檢測,而後每次有須要序列化的,生成一個Long型便可加密

Intellij idea用快捷鍵自動生成序列化ididea

序列化ID也能夠是自定義的,好比簡單的1L,只要調用方和被調用方約定一致便可;.net

transient關鍵字

  • transient修飾的變量,不會被序列化;
  • 靜態變量必定不會被序列化(類的屬性而不是對象的屬性值)
  • 一旦變量被transient修飾,變量將再也不是對象持久化的一部分,該變量內容在序列化後沒法得到訪問;
  • transient關鍵字只能修飾變量,而不能修飾方法和類;
  • 使用Externalizable能夠序列化transient修飾的變量
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Test;

import java.io.*;

@Slf4j
public class TestTransient {

//    private static final long serialVersionUID = 8204877978271765366L;

    @Test
    public void testTransi(){
        User user = new User("andy","123456");
        log.info("Before serializable,user={}",user.toString());
        try {
            ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
            os.writeObject(user);
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {

            ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:/user.txt"));
            user = (User) is.readObject();
            is.close();
            log.info("After serializable,username={},pwd={}",user.getUsername(),user.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    static class User implements Serializable {
        private static final long serialVersionUID = -3226152074589523662L;
        String username;
        transient String password;
    }
}

還須要注意的幾個問題

  • 虛擬機是否容許反序列化,不只取決於類路徑和功能代碼是否一致,一個很是重要的一點是兩個類的序列化 ID 是否一致
  • 要想將父類對象也序列化,就須要讓父類也實現Serializable 接口。若是父類不實現的話的,就須要有默認的無參的構造函數
  • 能夠嘗試使用序列化實現加密控制等(Override),參考RMI技術
  • 注意往一個文件中屢次寫入同一個對象的狀況code

    Java 序列化機制爲了節省磁盤空間,具備特定的存儲規則,當寫入文件的爲同一對象時,並不會再將對象的內容進行存儲,而只是再次存儲一份引用,上面增長的 5 字節的存儲空間就是新增引用和一些控制信息的空間。反序列化時,恢復引用關係,使得清單 3 中的 t1 和 t2 指向惟一的對象,兩者相等,輸出 true。該存儲規則極大的節省了存儲空間。htm

參考文章

相關文章
相關標籤/搜索