簡單來說,Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。
當實現java.io.Serializable介面的實體(類)沒有顯式地定義一個名為serialVersionUID,類型為long的變數時,Java序列化機制會根據編譯的class自動生成一個serialVersionUID作序列化版本比較用,這種情況下,只有同一次編譯生成的class才會生成相同的serialVersionUID 。
如果我們不希望通過編譯來強制劃分軟體版本,即實現序列化介面的實體能夠兼容先前版本,未作更改的類,就需要顯式地定義一個名為serialVersionUID,類型為long的變數,不修改這個變數值的序列化實體都可以相互進行串列化和反串列化。
serialVersionUID主要來判斷不同版本的兼容性。
當在反序列化的時候,位元組流中的版本號,就和serialVersionUID區比較,而生成它的對象。
如果你沒有設置,java序列化機制,也自動會給你分配一個。
其實這個東西沒必要去考慮!中軟卓越APP,你了解的更多
㈡ java類中serialversionuid 作用 是什麼舉個例子說明.
類中影響Serialization進程的特徵,兩邊的操作使用的類版本不同,但它們的 serialVersionUID 必須是一樣的。它是用來識別兩邊的類是否兼容的,兩邊不同時不應該繼續還原狀態,而是應該停止下來,因為有人把事情搞錯了。如果你的類沒有實現 java.io.Serializable 或 java.io.Externalizable,這個欄位則沒有意義。
如果你沒聽說過 Java Serialization (序列化,有人書翻譯成串列化),那去找些 serialization 介紹看看,下面說的第2段類結構變化時是中級水平的,理解 Java 的一些細節才能理解,多數情況下人們只提到第一種情況(類的結構沒有變化時),也只需要第一種情況。
當Serialization兩端(比如Socket兩端)使用一個類的不同版本時,我們必須提供 serialVersionUID,它可以用JDK自帶的 serialver 命令行來計算:
private static final long serialVersionUID = xxxx ;
如果類中出現了下面兩個方法,那麼將會被用到,否則使用默認的實現:
private void readObject(ObjectInputStream) throws IOException,ClassNotFoundException;
private void writeObject(ObjectOutputStream)throws IOException;
記住這里出現的方法和欄位都是 private.
新版本中僅增加了欄位或方法而沒有改變舊版本中已有的東西時,我們只要保證兩個版本中的 serialVersionUID 是一樣的就行了.
具體樣例可以看 JDK 源碼中的像 ArrayList 這些類的代碼的 readObject 和 writeObject 方法。
類的結構有些變化時,新版本對舊版本中某些東西進行了刪減時, Field 的變化我們需要在readObject和writeObject方法中進行處理
ObjectOutputStream.PutField 類可達到這個目的
只是保證兩個版本中的 serialVersionUID 一致是行不通的
類中必需兩個常量:
private static final long serialVersionUID;
private static final ObjectStreamField[] serialPersistentFields
下面樣例是當客戶端和服務端使用的類的版本不同並且類的結構也改變了,比如:
對方使用的類Entry是:
publicclassEntry12...{
privateStringname,email;
=12L;
}
現在我們改變了類的設計了:
publicclassEntry12...{
privateEntryInternalbasic;
=12L;
privateclassEntryInternal{
privateStringname,email;
}
}
/*這是一段代碼片段,我們假設新版本的類name&email兩個欄位進行了修改
*(這里我們放到一個內部類EntryInternal中),而舊版本中直接屬於這個類.
*
*請注意這里的欄位和方法的簽名,它們都是private的或者是常量.
*/
{
privateEntryInternalpair=newEntryInternal();
/*這是必要的,因為版本不同*/
=12L;
**這也是必要的,否則寫putFields時會拋出異常.
*Thisfieldwillbeusedby{@link#writeObject(ObjectOutputStream)},
*ifthisfieldismissing,
*{@linkjava.io.ObjectOutputStream.PutField#put(String,)}:
*anexception『java.lang.IllegalArgumentException:Nosuchobjectfield』willbethrew.
*/
[]serialPersistentFields=newObjectStreamField[]{
newObjectStreamField("name",String.class),//
newObjectStreamField("email",String.class),//
};
/*我們在這里不是直接寫出欄位,而把要寫出的欄位包裝起來,
我們按需交換欄位,而不是直接讀寫pair這個欄位.
*/
privatevoidreadObject(ObjectInputStreaminput)throwsIOException,ClassNotFoundException{
ObjectInputStream.GetFieldgetFields=input.readFields();
/*請注意:使用Serializable進行交換時不使用構造方法,所以這時pair還未初始化.*/
pair=newEntryInternal();
pair.name=(String)getFields.get("name",null);
pair.email=(String)getFields.get("email",null);
}
/*寫出時跟讀入時一樣*/
privatevoidwriteObject(ObjectOutputStreamoutput)throwsIOException{
ObjectOutputStream.PutFieldputFields=output.putFields();
putFields.put("name",pair==null?null:pair.name);
putFields.put("email",pair==null?null:pair.email);
output.writeFields();
}
…..
}
㈢ intent傳對象為什麼要序列化
傳遞。
三. Android中的兩種序列化機制
第一種: JAVA中的Serialize機制,譯成串列化、序列化……,其作用是能將數據對象存入位元組流當中,在需要時重新生成對象。主要應用是利用外部存儲設 備保存對象狀 態,以及通過網路傳輸對象等。
第二種:在Android系統中,定位為針對內存受限的設備,因此對性能要求更高,另外系統中採用了新的IPC(進程間通信)機制,必然要求使用性能更出色的對象傳輸方式。在這樣的環境下, Parcel被設計出來,其定位就是輕量級的高效的對象序列化和反序列化機制。
Android中序列化有以下幾個特
㈣ 避坑指南,Java中定時器Timer致命缺點,我差點就踩到了
這篇文章深入探討了Java中定時器Timer的使用與潛在問題,旨在幫助讀者在學習過程中避免可能的陷阱。首先,作者提到了一個簡單的Hello World案例,展示了如何創建並提交一個任務給定時器。然而,文章著重於揭示Timer的一個關鍵問題:它是一個單線程實現,這可能導致任務執行時的串列化,進而影響任務的延遲執行。
在案例1中,作者說明了Timer如何創建子線程,並通過死循環持續獲取並執行任務。如果主線程不提交任務,這個子線程就會一直等待。這個特性導致了問題:一旦提交任務,Timer就會不斷執行任務,除非使用cancel方法終止子線程。實際上,Timer的這種設計使得它在處理大量任務時可能存在延遲執行的問題,因為單線程環境下,任務執行是順序進行的。
為了進一步說明這個問題,文章引入了案例2。在該案例中,作者展示了如何在單線程環境中提交多個任務,並分析了任務執行的順序性對延遲的影響。通過觀察執行結果,可以清晰地看到任務之間的依賴關系,以及單線程環境下如何影響任務的執行順序。
文章還討論了Timer在實際應用中的局限性,以及如何通過使用線程池等多線程技術來優化定時任務的執行。作者強調了理解基礎概念的重要性,如可見性、原子性等,這些是深入學習多線程的基礎。同時,文章提醒讀者,在學習高級知識點之前,應先扎實基礎,如servlet、mvc思想等。
最後,文章總結了學習方法的核心:多動手實踐,從簡單的案例開始,逐漸深入。推薦了一本適合新手學習的多線程入門書籍,並強調了閱讀與實踐相結合的重要性。作者通過分享自己的經驗和體會,鼓勵讀者持續關注和學習,以期在Java領域取得進步。
總結:這篇文章不僅提供了關於Java中定時器Timer的使用與問題的深入分析,還分享了作者的學習心得與建議。通過提供案例分析和推薦學習資源,作者旨在幫助讀者在學習過程中避免常見陷阱,掌握更有效的學習方法。
㈤ 什麼是java序列化
Java 串列化技術可以使你將一個對象的狀態寫入一個Byte 流里,並且可以從其它地方把該Byte 流里的數據讀出來,重新構造一個相同的對象。這種機制允許你將對象通過網路進行傳播,並可以隨時把對象持久化到資料庫、文件等系統里。Java的串列化機制是RMI、EJB等技術的技術基礎。用途:利用對象的串列化實現保存應用程序的當前工作狀態,下次再啟動的時候將自動地恢復到上次執行的狀態。
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化後的對象進行讀寫操作,也可將流化後的對象傳輸於網路之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
序列化的實現:將需要被序列化的類實現Serializable介面,然後使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接著,使用ObjectOutputStream對象的writeObject(Object obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。