2014-07-07 49 views
7

我讀接口Serializable的文檔,其中我發現下面幾行:爲什麼基類(不實現Serializable)如果其子類實現Serializable,應該沒有參數構造函數?

允許非序列化類的子類型序列化,子類型可以承擔保存和恢復的狀態責任超類型的公共,受保護和(如果可訪問的)包字段。只有當它繼承的類有一個可訪問的無參數構造函數來初始化類的狀態時,該子類纔可以承擔這個責任。如果不是這種情況,則聲明一個類Serializable是錯誤的。該錯誤將在運行時檢測到。

但是,恢復對象的狀態時,基類的no-arg構造函數的作用是什麼?

+0

見http://www.jguru.com/faq/view.jsp?EID=251942 – GKislin

回答

13

當您試圖反序列化一個序列化對象,該機制必須創建對象的空實例,並填寫會員,對象恢復到它是序列化時的狀態。一個可序列化對象的構造函數在對象初次構造時會被調用,但是在反序列化過程中不會調用構造函數,因爲在技術上,您不是在構造該對象,而是將其重構爲前一個狀態。預計任何結構和子序列操作的影響已經被納入對象狀態。

無論何時構建任何類的對象,Java必須調用超類的構造函數以及超超類等。您可以使用super(...)指定超類的特定構造函數,或者如果不不指定超級構造函數,將使用默認的構造函數。無論如何,所有到根的類都被構建。

serlializable對象的反序列化不會導致構造函數調用,但是當有一個超類,它是不可序列化(也就是你擴展不可序列化的類與序列化類),那麼這個類是沒有預料到被反序列化,並且它沒有存儲/恢復其成員的機制。如果超類不是可序列化的,則反序列化機制需要調用零參數構造函數以確保重構的對象實例已正確初始化。

如果你沒有指定一個零參數的構造函數,反序列化的代碼不會提醒你這個問題,直到你的第一次嘗試反序列化類的一個對象。編譯時沒有警告。

此外,您的序列化的子類必須對存儲/從非序列化父類恢復任何成員的值責任。

+0

做基類的構造函數總是系列化運行? – YakRangi

+0

如果超類是可序列化的,那麼不需要arg構造函數,因爲派生類對象會自動保存基類部分,因爲該部分是可序列化的。] – YakRangi

+0

假設如果我們有一個arg構造函數,在不可序列化的基類中沒有arg構造函數,它們是否都被調用? – YakRangi

0

如果超類是不可序列比對序列化,子類的對象,就必須在子類中顯式實現Serializable接口。在這種情況下,超類必須有一個無參數的構造函數。

如果超類是不可序列然後從超類繼承的實例變量的所有值都將在反序列化過程中調用非序列超類的構造函數初始化。

相關問題