更新時(shí)間:2019-08-15 14:25:48 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽3301次

Java中的可序列化接口和可外部接口之間的區(qū)別是什么?
下面是我的版本Externalizable給我們提供writeExternal()和readExternal()方法,這讓我們靈活地控制Java序列化機(jī)制,而不是依賴于Java的默認(rèn)序列化。正確實(shí)現(xiàn)Externalizable接口可以顯著提高應(yīng)用程序的性能。
可序列化的方法有多少?如果沒(méi)有方法,那么可序列化接口的用途是什么?
可序列化Serializalbe接口存在于java.io包中,構(gòu)成了Java序列化機(jī)制的核心。它沒(méi)有任何方法,在Java中也稱為標(biāo)記接口。當(dāng)類實(shí)現(xiàn)java.io.Serializable接口時(shí),它將在Java中變得可序列化,并指示編譯器使用Java序列化機(jī)制序列化此對(duì)象。
什么是serialVersionUID?如果你不定義這個(gè),會(huì)發(fā)生什么?
serialVersionUID是一個(gè)privatestaticfinallong型ID,當(dāng)它被印在對(duì)象上時(shí),它通常是對(duì)象的哈希碼,你可以使用serialver這個(gè)JDK工具來(lái)查看序列化對(duì)象的serialVersionUID。SerialVerionUID用于對(duì)象的版本控制。也可以在類文件中指定serialVersionUID。不指定serialVersionUID的后果是,當(dāng)你添加或修改類中的任何字段時(shí),則已序列化類將無(wú)法恢復(fù),因?yàn)闉樾骂惡团f序列化對(duì)象生成的serialVersionUID將有所不同。
序列化時(shí),你希望某些成員不要序列化?你如何實(shí)現(xiàn)它?
這也是一些時(shí)候也問(wèn),如什么是瞬態(tài)trasient變量,瞬態(tài)和靜態(tài)變量會(huì)不會(huì)得到序列化等,所以,如果你不希望任何字段是對(duì)象的狀態(tài)的一部分,然后聲明它靜態(tài)或瞬態(tài)根據(jù)你的需要,這樣就不會(huì)是在Java序列化過(guò)程中被包含在內(nèi)。
如果類中的一個(gè)成員未實(shí)現(xiàn)可序列化接口,會(huì)發(fā)生什么情況?
如果嘗試序列化實(shí)現(xiàn)可序列化的類的對(duì)象,但該對(duì)象包含對(duì)不可序列化類的引用,則在運(yùn)行時(shí)將引發(fā)不可序列化異常NotSerializableException,這就是為什么我始終將一個(gè)可序列化警報(bào)(在我的代碼注釋部分中),代碼注釋最佳實(shí)踐之一,指示開(kāi)發(fā)人員記住這一事實(shí),在可序列化類中添加新字段時(shí)要注意。
如果類是可序列化的,但其超類不是,則反序列化后從超級(jí)類繼承的實(shí)例變量的狀態(tài)如何?
Java序列化過(guò)程僅在對(duì)象層次都是可序列化結(jié)構(gòu)中繼續(xù),即實(shí)現(xiàn)Java中的可序列化接口,并且從超級(jí)類繼承的實(shí)例變量的值將通過(guò)調(diào)用構(gòu)造函數(shù)初始化,在反序列化過(guò)程中不可序列化的超級(jí)類。一旦構(gòu)造函數(shù)鏈接將啟動(dòng),就不可能停止,因此,即使層次結(jié)構(gòu)中較高的類實(shí)現(xiàn)可序列化接口,也將執(zhí)行構(gòu)造函數(shù)。
是否可以自定義序列化過(guò)程,或者是否可以覆蓋Java中的默認(rèn)序列化過(guò)程?
答案是肯定的,你可以。對(duì)于序列化一個(gè)對(duì)象需調(diào)用ObjectOutputStream.writeObject(saveThisObject),并用ObjectInputStream.readObject()讀取對(duì)象,但Java虛擬機(jī)為你提供的還有一件事,是定義這兩個(gè)方法。如果在類中定義這兩種方法,則JVM將調(diào)用這兩種方法,而不是應(yīng)用默認(rèn)序列化機(jī)制。你可以在此處通過(guò)執(zhí)行任何類型的預(yù)處理或后處理任務(wù)來(lái)自定義對(duì)象序列化和反序列化的行為。
需要注意的重要一點(diǎn)是要聲明這些方法為私有方法,以避免被繼承、重寫或重載。由于只有Java虛擬機(jī)可以調(diào)用類的私有方法,你的類的完整性會(huì)得到保留,并且Java序列化將正常工作。在我看來(lái),這是在任何Java序列化面試中可以問(wèn)的最好問(wèn)題之一,一個(gè)很好的后續(xù)問(wèn)題是,為什么要為你的對(duì)象提供自定義序列化表單?

假設(shè)新類的超級(jí)類實(shí)現(xiàn)可序列化接口,如何避免新類被序列化?
如果類的Super類已經(jīng)在Java中實(shí)現(xiàn)了可序列化接口,那么它在Java中已經(jīng)可以序列化,因?yàn)槟悴荒苋∠涌?它不可能真正使它無(wú)法序列化類,但是有一種方法可以避免新類序列化。為了避免Java序列化,你需要在類中實(shí)現(xiàn)writeObject()和readObject()方法,并且需要從該方法引發(fā)不序列化異常NotSerializableException。這是自定義Java序列化過(guò)程的另一個(gè)好處,如上述序列化面試問(wèn)題中所述,并且通常隨著面試進(jìn)度,它作為后續(xù)問(wèn)題提出。
在Java中的序列化和反序列化過(guò)程中使用哪些方法?
在序列化基本上面試官試圖知道:你是否熟悉readObject()的用法、writeObject()、readExternal()和writeExternal()。Java序列化由java.io.ObjectOutputStream類完成。該類是一個(gè)篩選器流,它封裝在較低級(jí)別的字節(jié)流中,以處理序列化機(jī)制。要通過(guò)序列化機(jī)制存儲(chǔ)任何對(duì)象,我們調(diào)用ObjectOutputStream.writeObject(savethisobject),并反序列化該對(duì)象,我們稱之為ObjectInputStream.readObject()方法。調(diào)用以writeObject()方法在java中觸發(fā)序列化過(guò)程。關(guān)于readObject()方法,需要注意的一點(diǎn)很重要一點(diǎn)是,它用于從持久性讀取字節(jié),并從這些字節(jié)創(chuàng)建對(duì)象,并返回一個(gè)對(duì)象,該對(duì)象需要類型強(qiáng)制轉(zhuǎn)換為正確的類型。
假設(shè)你有一個(gè)類,它序列化并存儲(chǔ)在持久性中,然后修改了該類以添加新字段。如果對(duì)已序列化的對(duì)象進(jìn)行反序列化,會(huì)發(fā)生什么情況?
這取決于類是否具有其自己的serialVersionUID。正如我們從上面的問(wèn)題知道,如果我們不提供serialVersionUID,則Java編譯器將生成它,通常它等于對(duì)象的哈希代碼。通過(guò)添加任何新字段,有可能為該類新版本生成的新serialVersionUID與已序列化的對(duì)象不同,在這種情況下,Java序列化API將引發(fā)java.io.InvalidClassException,因此建議在代碼中擁有自己的serialVersionUID,并確保在單個(gè)類中始終保持不變。
Java序列化機(jī)制中的兼容更改和不兼容更改是什么?
真正的挑戰(zhàn)在于通過(guò)添加任何字段、方法或刪除任何字段或方法來(lái)更改類結(jié)構(gòu),方法是使用已序列化的對(duì)象。根據(jù)Java序列化規(guī)范,添加任何字段或方法都面臨兼容的更改和更改類層次結(jié)構(gòu)或取消實(shí)現(xiàn)的可序列化接口,有些接口在非兼容更改下。對(duì)于兼容和非兼容更改的完整列表,我建議閱讀Java序列化規(guī)范。
我們可以通過(guò)網(wǎng)絡(luò)傳輸一個(gè)序列化的對(duì)象嗎?
是的,你可以通過(guò)網(wǎng)絡(luò)傳輸序列化對(duì)象,因?yàn)镴ava序列化對(duì)象仍以字節(jié)的形式保留,字節(jié)可以通過(guò)網(wǎng)絡(luò)發(fā)送。你還可以將序列化對(duì)象存儲(chǔ)在磁盤或數(shù)據(jù)庫(kù)中作為Blob。
在Java序列化期間,哪些變量未序列化?
這個(gè)問(wèn)題問(wèn)得不同,但目的還是一樣的,Java開(kāi)發(fā)人員是否知道靜態(tài)和瞬態(tài)變量的細(xì)節(jié)。由于靜態(tài)變量屬于類,而不是對(duì)象,因此它們不是對(duì)象狀態(tài)的一部分,因此在Java序列化過(guò)程中不會(huì)保存它們。由于Java序列化僅保留對(duì)象的狀態(tài),而不是對(duì)象本身。瞬態(tài)變量也不包含在Java序列化過(guò)程中,并且不是對(duì)象的序列化狀態(tài)的一部分。在提出這個(gè)問(wèn)題之后,面試官會(huì)詢問(wèn)后續(xù)內(nèi)容,如果你不存儲(chǔ)這些變量的值,那么一旦對(duì)這些對(duì)象進(jìn)行反序列化并重新創(chuàng)建這些變量,這些變量的價(jià)值是多少?這是你們要考慮的。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)