爲何Java序列化要實現Serializable

(本內容是我在蒐集一些資料後的我的感悟,若有問題,請指出。蟹蟹)java

背景

對於Serializable,你們都知道是java中的一個接口。用來標記是否可序列化,該接口中什麼都沒有。網上大部分都只是告訴咱們,使用該接口可使對象序列化,從而能夠便於存儲和傳輸。而若是不實現該接口,則在序列化的時候會拋出異常。安全

疑問

讀到這裏或許有不少同窗會產生疑問:網絡

一個空接口,裏面啥都沒有。爲何java設計的時候必定要實現Serializable才能序列化?不能去掉Serializable這個接口,讓每一個對象都能序列化嗎?app

解答

筆者經過對網絡上的答案進行瀏覽,雖然大部分都是解釋Serializable的做用,沒有說爲何要這樣。可是最終仍是找到一個比較有說服力的解釋。post

總的就是說安全性問題,具體緣由看法釋:假如沒有一個接口(即沒有Serializable來標記是否能夠序列化),讓全部對象均可以序列化。那麼全部對象經過序列化存儲到硬盤上後,均可以在序列化獲得的文件中看到屬性對應的值(後面將會經過代碼展現)。因此最後爲了安全性(即不讓一些對象中私有屬性的值被外露),不能讓全部對象均可以序列化。要讓用戶本身來選擇是否能夠序列化,所以須要一個接口來標記該類是否可序列化。this

證實

首先咱們先創建一個person類,該類有三個屬性:一個年紀(我願意告訴別人),一個姓名(我願意告訴別人),一個祕密(我不肯意告訴別人)。具體代碼以下。編碼

public class Person implements Serializable {

    private int age;
    private String name;
    //個人祕密
    private String secret;

    public Person(int age, String name, String secret) {
        this.age = age;
        this.name = name;
        this.secret = secret;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }
}
複製代碼

而後就是咱們將這個Person的對象序列化存入硬盤啦。spa

public class Main {
    public static void main(String[] args) {
        /** * person對象有三個屬性, * 一個是個人年紀(可讓別人知道) * 一個是個人名字(可讓別人知道) * 一個是個人祕密(我不想告訴別人) */
        Person person = new Person(22, "小明", "我喜歡暢暢");
        // 把對象存入硬盤
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person"));){
            oos.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
複製代碼

執行這段代碼後,會在項目目錄下發現一個person文件。而後你們會發現有些對象的值居然是明文存在裏面。例如我喜歡暢暢這是個人祕密鴨。 設計

全部若是什麼對象均可以序列化的話,那麼對象的一些私有屬性都有可能被惡意代碼獲取的闊能。因此呢,java設計人員爲了安全起見,不容許全部的對象都能序列化,而是要用戶編碼的時候去指定能夠序列化的類。code


若是一個對象須要序列化,可是又有一些私密信息不想持久化呢?(例如單獨將咱們person的secret屬性屏蔽持久化)

你們可使用static或者transient修飾變量,具體怎麼用呢?請移步happyjava同窗的blog。 謝謝你們的閱讀,以上是我我的見解,若有更多的見解能夠評論一塊兒交流。

相關文章
相關標籤/搜索