天天看點

關于Java中Serializable的一些問題

       在面試中我常常會考察Serializable相關的問題,我認為這是一個很基礎的知識點,是對候選人基礎是否紮實的考察。但是結果有點出乎意料,候選人往往隻是知道它和序列化有關,而對于其中的細節以及更深層次的原理都不是很清楚。是以,我決定整理一下Serializable相關的一些問題,希望能夠對不了解的同學有所幫助。

       一個類實作Serializable接口後可以被序列化。這個接口沒有方法和字段,隻是用來标志這個類可以被序列化。

關于serialVersionUID

       一個類如果實作了Serializable接口,同時也需要定義一個serialVersionUID,如下:

private static final long serialVersionUID = 1L;

        我相信很多同學一直不太明白這個 serialVersionUID 字段的真正作用,如果我們不去定義它會有什麼樣的問題。

        serialVersionUID按照字面意思來了解就是序列化的版本号,這個serialVersionUID是用來輔助對象的序列化與反序列化的,原則上序列化後的資料當中的serialVersionUID與目前類中的serialVersionUID一緻,該對象才能被反序列化成功。

        這個serialVersionUID的工作原理大緻是這樣的:在序列化的時候系統将serialVersionUID寫入到序列化的檔案中去,反序列化的時候系統會先去檢測檔案中的serialVersionUID是否跟目前的serialVersionUID一緻,如果一緻就反序列化成功,否則就說明目前類跟序列化後的類發生了變化,反序列化時就會發生crash,并且會抛出異常:

關于Java中Serializable的一些問題

       如果我們沒有指定serialVersionUID,那麼對象在被序列化的時候,系統會根據類名、變量等資訊自動生成一個serialVersionUID,如果我們修改了對象的成員,那麼這個serialVersionUID就會發生變化。當對象被反序列化的時候,這兩個值不相等,就會發生crash。

       是以,如果我們需要對象在序列化後的改變不影響反序列化,就必須明确指定類的serialVersionUID。

繼承問題

       如果父類實作了serializable接口,那麼子類實作還是不實作接口都一樣能夠被序列化。

       如果一個類可被序列化,如果該類有父類,父類實作了Serializable則父類對象字段可以序列化,沒實作,則父類對象字段不能被序列化。  、

       如果父類定義了serialVersionUID,子類也是需要定義自己的serialVersionUID。

成員變量的序列化問題

       如果一個類實作了Serializable接口,但是它内部有成員變量并不是Serializable類型的,如果我們去序列化這個類的對象,就會抛出下面的異常:

關于Java中Serializable的一些問題

       解決的辦法是讓這個成員變量也實作Serializable接口,或者選擇用transient去修飾這個成員變量,在序列化的時候就會忽略這個變量。

歡迎關注我的微信公衆号,收到最新的推送文章

關于Java中Serializable的一些問題