Java序列化和反序列化示例介紹
以前用序列化都是一些方法需要才實現(xiàn)的,后來業(yè)務(wù)需求要深拷貝才去研究。參閱了別人博客得出一些總結(jié)。
序列化是為了把Java對象轉(zhuǎn)化為字節(jié)序列(字節(jié)流)的過程。然后深拷貝是通過對流的操作來實現(xiàn)的,序列化后數(shù)據(jù)方便存儲和傳輸。反序列化則是把字節(jié)序列反序列化為Java對象
存儲方便:因為對象會被回收,序列化后可以持續(xù)化存儲在磁盤中
傳輸方便:字節(jié)序列(二進制形式)可以進行網(wǎng)絡(luò)傳輸和傳播。
最好設(shè)置一個SerialversionUID,因為序列化和反序列化是對比SerialversionUID來進行的,雖然不設(shè)置接口也會默認生成一個,但是要知道序列化對象過程一般都是對象->序列化->存儲或傳輸->反序列化。
舉個例子:
先創(chuàng)建一個實體類Student
import lombok.Data; import java.io.Serializable; @Data public class Student implements Serializable { private Integer id; private String name; private String sex; }
然后創(chuàng)建一個測試類SerializableTest
import serialization.entity.Student; import java.io.*; public class SerializableTest { public static void main(String[] args) throws Exception { serializeStudent(); Student student = deserializeStudent(); System.out.println("name:" + student.getName()); System.out.println("sex:" + student.getSex()); } private static void serializeStudent() throws IOException { Student student = new Student(); student.setId(1); student.setName("張三"); student.setSex("male"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream( new File("F:/student.txt"))); out.writeObject(student); System.out.println("序列化成功"); out.close(); } private static Student deserializeStudent() throws Exception { ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt"))); Student student = (Student) in.readObject(); System.out.println("反序列化成功"); return student; } }
執(zhí)行結(jié)果:
序列化成功 反序列化成功 name:張三 sex:male
這個時候沒有指定SerialversionUID也是可以成功的,但對象->序列化->存儲或傳輸->反序列化,咱們在反序列化操作之前對Student類修改呢?
這個時候咱們修改一下代碼,先注釋掉反序列化代碼,先進行序列化。
import serialization.entity.Student; import java.io.*; public class SerializableTest { public static void main(String[] args) throws Exception { serializeStudent(); // Student student = deserializeStudent(); // System.out.println("name:" + student.getName()); // System.out.println("sex:" + student.getSex()); } private static void serializeStudent() throws IOException { Student student = new Student(); student.setId(1); student.setName("張三"); student.setSex("male"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream( new File("F:/student.txt"))); out.writeObject(student); System.out.println("序列化成功"); out.close(); } // private static Student deserializeStudent() throws Exception { // ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt"))); // Student student = (Student) in.readObject(); // System.out.println("反序列化成功"); // return student; // } }
運行結(jié)果:
序列化成功
修改Student類
import lombok.Data; import java.io.Serializable; @Data public class Student implements Serializable { private Integer id; private String name; private String sex; private String address; }
注釋掉序列化方法,進行反序列化
import serialization.entity.Student; import java.io.*; public class SerializableTest { public static void main(String[] args) throws Exception { // serializeStudent(); Student student = deserializeStudent(); System.out.println("name:" + student.getName()); System.out.println("sex:" + student.getSex()); } // private static void serializeStudent() throws IOException { // Student student = new Student(); // student.setId(1); // student.setName("張三"); // student.setSex("male"); // // ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream( // new File("F:/student.txt"))); // out.writeObject(student); // System.out.println("序列化成功"); // out.close(); // } private static Student deserializeStudent() throws Exception { ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:/student.txt"))); Student student = (Student) in.readObject(); System.out.println("反序列化成功"); return student; } }
執(zhí)行結(jié)果:
Exception in thread "main" java.io.InvalidClassException: serialization.entity.Student; local class incompatible: stream classdesc serialVersionUID = 3846952599709361171, local class serialVersionUID = -4606152942663467236 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at serialization.demo.SerializableTest.deserializeStudent(SerializableTest.java:30) at serialization.demo.SerializableTest.main(SerializableTest.java:10) Process finished with exit code 1
可以看出兩次的執(zhí)行的SerialversionUID不匹配,導(dǎo)致產(chǎn)生java.io.InvalidClassException異常,所以只要指定了SerialversionUID就不會報異常。
//指定serialVersionUID正確寫法 private static final long serialVersionUID = 3846952599709361171L; //如果已經(jīng)進行序列化了不知道SerialversionUID,可以通過反射獲取 Object obj = Student.class.newInstance(); Field field = Student.class.getDeclaredField("serialVersionUID"); field.setAccessible(true); System.out.println(field.getLong(obj));
最后需要知道的一點就是字節(jié)流和字符流的區(qū)別。
字節(jié)流:傳輸過程中,傳輸數(shù)據(jù)的最基本單位是字節(jié)的流。
字符流:傳輸過程中,傳輸數(shù)據(jù)的最基本單位是字符的流。
這樣講可能有點不知所云,字節(jié)其實就是Java的八大基本類型Byte(比特)單位,而字符通常是’A’、‘B’、’$’、’&'等,字節(jié)大小則取決于你是什么編碼(環(huán)境),如下:
ASCII 碼中,一個英文字母(不分大小寫)為一個字節(jié),一個中文漢字為兩個字節(jié)。
UTF-8 編碼中,一個英文字為一個字節(jié),一個中文為三個字節(jié)。
Unicode 編碼中,一個英文為一個字節(jié),一個中文為兩個字節(jié)。
符號:英文標點為一個字節(jié),中文標點為兩個字節(jié)。例如:英文句號 . 占1個字節(jié)的大小,中文句號 。
占2個字節(jié)的大小。UTF-16 編碼中,一個英文字母字符或一個漢字字符存儲都需要 2 個字節(jié)(Unicode 擴展區(qū)的一些漢字存儲需要 4 個字節(jié))。
UTF-32 編碼中,世界上任何字符的存儲都需要 4 個字節(jié)。
到此這篇關(guān)于Java序列化和反序列化示例介紹的文章就介紹到這了,更多相關(guān)Java序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java+ElasticSearch+Pytorch實現(xiàn)以圖搜圖功能
這篇文章主要為大家詳細介紹了Java如何利用ElasticSearch和Pytorch實現(xiàn)以圖搜圖功能,文中的示例代碼講解詳細,具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下2023-06-06Spring?Boot項目如何優(yōu)雅實現(xiàn)Excel導(dǎo)入與導(dǎo)出功能
在我們平時工作中經(jīng)常會遇到要操作Excel的功能,比如導(dǎo)出個用戶信息或者訂單信息的Excel報表,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot項目中如何優(yōu)雅實現(xiàn)Excel導(dǎo)入與導(dǎo)出功能的相關(guān)資料,需要的朋友可以參考下2022-06-06詳解Spring Data JPA動態(tài)條件查詢的寫法
本篇文章主要介紹了Spring Data JPA動態(tài)條件查詢的寫法 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06IDEA生成patch和使用patch的方法實現(xiàn)
比如你本地修復(fù)的 bug,需要把增量文件發(fā)給客戶,很多場景下大家都需要手工整理修改的文件,并整理好目錄,這個很麻煩,那有沒有簡單的技巧呢?本文主要介紹了IDEA生成patch和使用patch的方法實現(xiàn),感興趣的可以了解一下2023-08-08Java中使用輾轉(zhuǎn)相除法求最大公約數(shù)
這篇文章主要介紹了Java中使用輾轉(zhuǎn)相除法求最大公約數(shù),本文直接給出代碼實例,需要的朋友可以參考下2015-05-05