更新時間:2019-08-15 14:25:48 來源:動力節點 瀏覽2697次
Java中的可序列化接口和可外部接口之間的區別是什么?
下面是我的版本Externalizable給我們提供writeExternal()和readExternal()方法,這讓我們靈活地控制Java序列化機制,而不是依賴于Java的默認序列化。正確實現Externalizable接口可以顯著提高應用程序的性能。
可序列化的方法有多少?如果沒有方法,那么可序列化接口的用途是什么?
可序列化Serializalbe接口存在于java.io包中,構成了Java序列化機制的核心。它沒有任何方法,在Java中也稱為標記接口。當類實現java.io.Serializable接口時,它將在Java中變得可序列化,并指示編譯器使用Java序列化機制序列化此對象。
什么是serialVersionUID?如果你不定義這個,會發生什么?
serialVersionUID是一個privatestaticfinallong型ID,當它被印在對象上時,它通常是對象的哈希碼,你可以使用serialver這個JDK工具來查看序列化對象的serialVersionUID。SerialVerionUID用于對象的版本控制。也可以在類文件中指定serialVersionUID。不指定serialVersionUID的后果是,當你添加或修改類中的任何字段時,則已序列化類將無法恢復,因為為新類和舊序列化對象生成的serialVersionUID將有所不同。
序列化時,你希望某些成員不要序列化?你如何實現它?
這也是一些時候也問,如什么是瞬態trasient變量,瞬態和靜態變量會不會得到序列化等,所以,如果你不希望任何字段是對象的狀態的一部分,然后聲明它靜態或瞬態根據你的需要,這樣就不會是在Java序列化過程中被包含在內。
如果類中的一個成員未實現可序列化接口,會發生什么情況?
如果嘗試序列化實現可序列化的類的對象,但該對象包含對不可序列化類的引用,則在運行時將引發不可序列化異常NotSerializableException,這就是為什么我始終將一個可序列化警報(在我的代碼注釋部分中),代碼注釋最佳實踐之一,指示開發人員記住這一事實,在可序列化類中添加新字段時要注意。
如果類是可序列化的,但其超類不是,則反序列化后從超級類繼承的實例變量的狀態如何?
Java序列化過程僅在對象層次都是可序列化結構中繼續,即實現Java中的可序列化接口,并且從超級類繼承的實例變量的值將通過調用構造函數初始化,在反序列化過程中不可序列化的超級類。一旦構造函數鏈接將啟動,就不可能停止,因此,即使層次結構中較高的類實現可序列化接口,也將執行構造函數。
是否可以自定義序列化過程,或者是否可以覆蓋Java中的默認序列化過程?
答案是肯定的,你可以。對于序列化一個對象需調用ObjectOutputStream.writeObject(saveThisObject),并用ObjectInputStream.readObject()讀取對象,但Java虛擬機為你提供的還有一件事,是定義這兩個方法。如果在類中定義這兩種方法,則JVM將調用這兩種方法,而不是應用默認序列化機制。你可以在此處通過執行任何類型的預處理或后處理任務來自定義對象序列化和反序列化的行為。
需要注意的重要一點是要聲明這些方法為私有方法,以避免被繼承、重寫或重載。由于只有Java虛擬機可以調用類的私有方法,你的類的完整性會得到保留,并且Java序列化將正常工作。在我看來,這是在任何Java序列化面試中可以問的最好問題之一,一個很好的后續問題是,為什么要為你的對象提供自定義序列化表單?
假設新類的超級類實現可序列化接口,如何避免新類被序列化?
如果類的Super類已經在Java中實現了可序列化接口,那么它在Java中已經可以序列化,因為你不能取消接口,它不可能真正使它無法序列化類,但是有一種方法可以避免新類序列化。為了避免Java序列化,你需要在類中實現writeObject()和readObject()方法,并且需要從該方法引發不序列化異常NotSerializableException。這是自定義Java序列化過程的另一個好處,如上述序列化面試問題中所述,并且通常隨著面試進度,它作為后續問題提出。
在Java中的序列化和反序列化過程中使用哪些方法?
在序列化基本上面試官試圖知道:你是否熟悉readObject()的用法、writeObject()、readExternal()和writeExternal()。Java序列化由java.io.ObjectOutputStream類完成。該類是一個篩選器流,它封裝在較低級別的字節流中,以處理序列化機制。要通過序列化機制存儲任何對象,我們調用ObjectOutputStream.writeObject(savethisobject),并反序列化該對象,我們稱之為ObjectInputStream.readObject()方法。調用以writeObject()方法在java中觸發序列化過程。關于readObject()方法,需要注意的一點很重要一點是,它用于從持久性讀取字節,并從這些字節創建對象,并返回一個對象,該對象需要類型強制轉換為正確的類型。
假設你有一個類,它序列化并存儲在持久性中,然后修改了該類以添加新字段。如果對已序列化的對象進行反序列化,會發生什么情況?
這取決于類是否具有其自己的serialVersionUID。正如我們從上面的問題知道,如果我們不提供serialVersionUID,則Java編譯器將生成它,通常它等于對象的哈希代碼。通過添加任何新字段,有可能為該類新版本生成的新serialVersionUID與已序列化的對象不同,在這種情況下,Java序列化API將引發java.io.InvalidClassException,因此建議在代碼中擁有自己的serialVersionUID,并確保在單個類中始終保持不變。
Java序列化機制中的兼容更改和不兼容更改是什么?
真正的挑戰在于通過添加任何字段、方法或刪除任何字段或方法來更改類結構,方法是使用已序列化的對象。根據Java序列化規范,添加任何字段或方法都面臨兼容的更改和更改類層次結構或取消實現的可序列化接口,有些接口在非兼容更改下。對于兼容和非兼容更改的完整列表,我建議閱讀Java序列化規范。
我們可以通過網絡傳輸一個序列化的對象嗎?
是的,你可以通過網絡傳輸序列化對象,因為Java序列化對象仍以字節的形式保留,字節可以通過網絡發送。你還可以將序列化對象存儲在磁盤或數據庫中作為Blob。
在Java序列化期間,哪些變量未序列化?
這個問題問得不同,但目的還是一樣的,Java開發人員是否知道靜態和瞬態變量的細節。由于靜態變量屬于類,而不是對象,因此它們不是對象狀態的一部分,因此在Java序列化過程中不會保存它們。由于Java序列化僅保留對象的狀態,而不是對象本身。瞬態變量也不包含在Java序列化過程中,并且不是對象的序列化狀態的一部分。在提出這個問題之后,面試官會詢問后續內容,如果你不存儲這些變量的值,那么一旦對這些對象進行反序列化并重新創建這些變量,這些變量的價值是多少?這是你們要考慮的。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習