java的序列化Serializable

康小孩發表於2020-11-22

Serializable的作用: 是java提供的一個序列化介面,用來為物件提供標準的序列化和反序列化操作。使用Serializable做序列化比較簡單。
使用方式:

  • 直接實現Serializable介面
  • 宣告一個靜態值serialVersionUID。這個值並不是必須的,但是最好手動序列化。因為不設定這個值java會自動根據當前物件的hash生成一個值,但是這樣容易引發一些問題,比如反序列化時程式崩潰。我們可以從後面的例子中看到。

注意: 1、序列化的時候會將Serializable的值一起寫入檔案,然後反序列化的時候再利用檔案中的Serializable值和當前類的Serializable進行對比,如果不一致則會出現反序列化失敗的問題,會直接程式崩潰,後面會舉例。 2、靜態變數是屬於類不屬於物件,所以不參與序列化過程。

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String mUserName;
    private int mUserAge;

    public User(String userName, int userAge) {
        this.mUserName = userName;
        this.mUserAge = userAge;
    }

    public String getUserName() {
        return mUserName;
    }

    public int getUserAge() {
        return mUserAge;
    }
}
  • 如果不手動設定serialVersionUID 會發生什麼?
public class User implements Serializable {
    private String mUserName;
    private int mUserAge;

    public User(String userName, int userAge) {
        this.mUserName = userName;
        this.mUserAge = userAge;
    }

    public String getUserName() {
        return mUserName;
    }

    public int getUserAge() {
        return mUserAge;
    }
}

public class Client {
    public static void main(String[] args) {
        User user = new User("Kyle", 18);
        //先序列化到一個檔案中
        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
            out.writeObject(user);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

//        try {
//            ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
//            User userNew = (User) in.readObject();
//            in.close();
//            System.out.println("反序列化結果:" + userNew.getUserName() + userNew.getUserAge());
//        } catch (IOException e) {
//            e.printStackTrace();
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
    }
}
public class Client {
    public static void main(String[] args) {
//        User user = new User("Kyle", 18);
//        try {
//            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
//            out.writeObject(user);
//            out.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
		//然後反序列化
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
            User userNew = (User) in.readObject();
            in.close();
            System.out.println("反序列化結果:" + userNew.getUserName() + userNew.getUserAge());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

輸出結果:
在這裡插入圖片描述
但是當後面我們在User類中增加一個欄位時:由於此時在反序化時User類自動生成的Serializable已經自動改變,所以反序化就會失敗,丟擲JE。所以我們應該手動設定Serializable,一邊可以最大化的反序化原始資料。

public class User implements Serializable {
    private String mUserName;
    private int mUserAge;
    private boolean mIsMale;

    public User(String userName, int userAge) {
        this.mUserName = userName;
        this.mUserAge = userAge;
    }

    public String getUserName() {
        return mUserName;
    }

    public int getUserAge() {
        return mUserAge;
    }
}

在這裡插入圖片描述
我們也可以在實驗一下設定serialVersionUID的情況,即使我們新增加欄位,還是可以反序列化出資料。

相關文章