最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的序列化(Serializable)和反序列化

 更新時(shí)間:2023年09月28日 10:20:27   作者:飛鷹279  
這篇文章主要介紹了Java中的序列化(Serializable)和反序列化,?JAVA序列化與反序列化就是JAVA對(duì)象與一串字節(jié)流之間的相互轉(zhuǎn)換,?我們?cè)诔绦蛑袆?chuàng)建的JAVA對(duì)象只存在于JVM中,需要的朋友可以參考下

JAVA序列化與反序列化

JAVA序列化與反序列化就是JAVA對(duì)象與一串字節(jié)流之間的相互轉(zhuǎn)換, 我們?cè)诔绦蛑袆?chuàng)建的JAVA對(duì)象只存在于JVM中, 當(dāng)程序退出時(shí), 這些對(duì)象也就消失了, 而序列化正是為了將這些對(duì)象保存起來(lái)以?xún)H將來(lái)使用,也可以將已經(jīng)序列化的對(duì)象傳送給其他JVM來(lái)使用,這些序列化的字節(jié)流是于JVM無(wú)關(guān)的, 也就是說(shuō)一個(gè)JVM序列化的對(duì)象可以在另一個(gè)JVM中反序列化

使用JAVA提供的序列化機(jī)制有以下兩條需要遵守的條件:

  • 該類(lèi)必須直接實(shí)現(xiàn)java.io.Serializable接口或者間接從其繼承樹(shù)中實(shí)現(xiàn)該接口(也就是他的某個(gè)父類(lèi)實(shí)現(xiàn)了這個(gè)接口);
  • 對(duì)于該類(lèi)的所有無(wú)法序列化的屬性(本文指字段field, 而不是嚴(yán)格意義上的屬性property, 下同)必須使用transient修飾.

對(duì)以上兩個(gè)條件的補(bǔ)充說(shuō)明:

  1. 從其繼承樹(shù)中實(shí)現(xiàn)Serializable接口指的是該類(lèi)的某個(gè)父類(lèi)實(shí)現(xiàn)了這個(gè)接口, 要注意的是Object類(lèi)并沒(méi)有實(shí)現(xiàn)該接口, 也就是說(shuō)默認(rèn)的情況下我們定義的類(lèi)是不支持序列化的, 而JDK提供的某些類(lèi)如String, 數(shù)組等實(shí)現(xiàn)了該接口;
  2. 無(wú)法序列化的屬性包括兩種:一種是主觀上不想保存的屬性, 如動(dòng)態(tài)生成的屬性或者考慮到性能上的要求不準(zhǔn)備保存的屬性; 另一種是由于該屬性的類(lèi)型沒(méi)有實(shí)現(xiàn)序列化而無(wú)法保存的屬性, 如Thread類(lèi)型的屬性;
  3. 序列化機(jī)制并不要求該類(lèi)具有一個(gè)無(wú)參的構(gòu)造方法, 因?yàn)樵诜葱蛄谢倪^(guò)程中實(shí)際上是去其繼承樹(shù)上找到一個(gè)沒(méi)有實(shí)現(xiàn)Serializable接口的父類(lèi)(最終會(huì)找到Object), 然后構(gòu)造該類(lèi)的對(duì)象, 再逐層往下的去設(shè)置各個(gè)可以反序列化的屬性(也就是沒(méi)有被transient修飾的非靜態(tài)屬性).

在使用JDK提供的序列化機(jī)制時(shí)需要借助一對(duì)I/O流, ObjectOutputStream和ObjectInputStream, 這兩個(gè)流分別是進(jìn)行序列化和反序列化操作, 通過(guò)ObjectOutputStream類(lèi)的writeObject(obj)方法可以將對(duì)象寫(xiě)入到輸出流中, 通過(guò)ObjectInputStream類(lèi)的readObject()方法可以從該輸入流中反序列化該對(duì)象出來(lái). 如下面的例子就是將Student類(lèi)的一個(gè)對(duì)象序列化保存到文件中, 并從該文件反序列化重新構(gòu)建出該對(duì)象(僅僅為了展示如何使用,對(duì)異常及流的處理末加以注意):

   class Student implements Serializable{
      private String name;
      public Student(String name){
         this.name = name;
      }
      public String getName(){
         return name;
      }
   }
   class StudentSerializer{
      public static void main(String[] args) throws Exception{
         // create a Student object
         Student st = new Student("jason");
        // serialize the st to jason.se file
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("jason.se"));
        oos.writeObject(st);
        oos.close();
        // deserialize the object from jason.se
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("jason.se"));
        Student jason = (Student) ois.readObject();
        ois.close();
       // verify the name field of jason object
       assert "jason".equals(jason.getName());
      }
   }

從上例可以看出, JDK提供的序列化機(jī)制使用起來(lái)相當(dāng)簡(jiǎn)單, 要注意的是:

  1. 在反序列的JVM上必須能夠找到該類(lèi)(有可能序列化和反序列化并不是在同一個(gè)JVM上進(jìn)行的), 否則就會(huì)拋出ClassNotFoundException;
  2. 由于ObjectInputStream.readObject()方法可以反序列化任何類(lèi)的對(duì)象, 所以其返回類(lèi)型為Object, 我們需要將其強(qiáng)轉(zhuǎn)成具體的類(lèi);
  3. 如何對(duì)不滿(mǎn)足序列化機(jī)制的兩個(gè)要求的類(lèi)進(jìn)行序列化, 則會(huì)拋出NotSerializableException;
  4. 如果JVM發(fā)現(xiàn)序列化與反序列化的類(lèi)文件"不相同", 則會(huì)拋出InvalidClassException.

JVM如何判斷序列化與反序列化的類(lèi)文件是否相同呢? 并不是說(shuō)兩個(gè)類(lèi)文件要完全一樣, 而是通過(guò)類(lèi)的一個(gè)私有屬性serialVersionUID來(lái)判斷的, 如果我們沒(méi)有顯示的指定這個(gè)屬性, 那么JVM會(huì)自動(dòng)使用該類(lèi)的hashcode值來(lái)設(shè)置這個(gè)屬性, 這個(gè)時(shí)候如果我們對(duì)類(lèi)進(jìn)行改變(比如說(shuō)加一個(gè)屬性或者刪掉一個(gè)屬性)就會(huì)導(dǎo)致serialVersionUID不同, 所以對(duì)于準(zhǔn)備序列化的類(lèi), 一般情況下我們都會(huì)顯示的設(shè)置這個(gè)屬性, 這樣及時(shí)以后我們對(duì)該類(lèi)進(jìn)行了某些改動(dòng), 只要這個(gè)值保持一樣, JVM就還是會(huì)認(rèn)為這個(gè)類(lèi)文件是沒(méi)有變的, 需要注意的是這種改變不包括繼承結(jié)構(gòu)的變化. 該屬性必須以下面的修飾方法來(lái)設(shè)置:

//當(dāng)然這個(gè)值可以自己指定, 也可以通過(guò)JDK提供的serializer來(lái)查看其默認(rèn)的hashcode值.
    private static final long serialVersionUID = -4333316296251054416L;  

由于JDK提供的這種默認(rèn)的序列化機(jī)制是簡(jiǎn)單的將對(duì)象變成字節(jié)流, 有時(shí)候并不滿(mǎn)足我們的要求, 比如考慮到加密, 或者在反序列化完了后需要調(diào)用某個(gè)方法來(lái)初始化transient的屬性等等, JDK提供了一種擴(kuò)展的方法來(lái)增加對(duì)序列化和反序列化的控制. 那就是可以讓序列化的對(duì)象實(shí)現(xiàn)下面兩個(gè)固定的方法(注意修飾符和結(jié)構(gòu)是固定的, throws的exception可以變通, 比如直接寫(xiě)成throws Exception也是可以的):

private void writeObject(ObjectOutputStream oos) throws IOException {}
   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{}

JVM在序列化和反序列化的過(guò)程中如果發(fā)現(xiàn)我們的類(lèi)實(shí)現(xiàn)了這兩個(gè)方法, 就會(huì)在writeObject(obj)和readObject()的時(shí)候?qū)⒖刂屏鬓D(zhuǎn)交給這兩個(gè)方法, 這樣我們就可以來(lái)執(zhí)行一些額外的操作, 同時(shí)可以在這兩個(gè)方法中調(diào)用ObjectOutputStream的defaultWriteObject()和ObjectInputStream的defaultReadObject()來(lái)讓JVM幫我們來(lái)執(zhí)行底部的具體序列化和反序列化操作, 如下例所示:

   class Student implements Serializable{
      private String name;
      public Student(String name){
         this.name = name;
      }
      public String getName(){
        return name;
      }
      private void writeObject(ObjectOutputStream oos) throws IOException {
         oos.defaultWriteObject();
         // 可以執(zhí)行其他的操作, 比如對(duì)反列化的文件進(jìn)行加密等等
      }
      private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
         ois.defaultReadObject();
         //可以調(diào)用其他方法來(lái)進(jìn)行額外的初始化操作
      }
   }

注意此時(shí)僅僅是對(duì)需要序列化的類(lèi)增加了這兩個(gè)私有方法, 而對(duì)如何將其序列化和反序列化上并沒(méi)有任何改變, 也就是說(shuō)我們的StudentSerializer類(lèi)并不需要做任何改變, JVM的序列化機(jī)制會(huì)自行來(lái)控制, 當(dāng)然如果我們?cè)趦蓚€(gè)私有的writeObject()和readObject()中并沒(méi)有調(diào)回ObjectOutputStream的defaultWriteObject()和ObjectInputStream的defaultReadObject()方法的話(huà), 那就并沒(méi)有序列化了(除非你自己實(shí)現(xiàn)這個(gè)序列化和反序列化的過(guò)程)

到此這篇關(guān)于Java中的序列化(Serializable)和反序列化的文章就介紹到這了,更多相關(guān)Java序列化與反序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Fork/Join框架

    Java Fork/Join框架

    Fork/Join框架是Java7中新增的一項(xiàng)特性,也是Java7平臺(tái)的其中一項(xiàng)主要改進(jìn)。下面我們就來(lái)簡(jiǎn)單探討下Java的Fork/Join框架
    2016-09-09
  • 每天學(xué)Java!一分鐘了解JRE與JDK

    每天學(xué)Java!一分鐘了解JRE與JDK

    每天學(xué)Java!一分鐘了解JRE與JDK,什么是JRE?什么是JDK?什么是JVM?相信通過(guò)本文大家都會(huì)有所了解,感興趣的小伙伴們可以參考一下
    2016-07-07
  • IDEA包下不能建包問(wèn)題的解決過(guò)程

    IDEA包下不能建包問(wèn)題的解決過(guò)程

    在IDEA中,新建包時(shí)出現(xiàn)問(wèn)題,是因?yàn)楣催x了“Compact Middle Packages”選項(xiàng),導(dǎo)致包結(jié)構(gòu) becoming緊湊型,取消該選項(xiàng)后,包結(jié)構(gòu)恢復(fù)正常
    2026-03-03
  • Mybatis批量新增的三種實(shí)現(xiàn)方式

    Mybatis批量新增的三種實(shí)現(xiàn)方式

    文章講述了在Java中進(jìn)行批量操作的最佳實(shí)踐,包括使用MyBatis的ExecutorType.BATCH模式,作者建議根據(jù)實(shí)際需求選擇是否進(jìn)行批量操作,因?yàn)榕坎僮鞑⒉豢偸悄芴嵘阅?且有副作用,如無(wú)法獲取自增ID等
    2024-12-12
  • Java實(shí)現(xiàn)BCrypt密碼加密的示例

    Java實(shí)現(xiàn)BCrypt密碼加密的示例

    本文介紹了MySQL數(shù)據(jù)庫(kù)密碼安全存儲(chǔ)的方法,使用BCrypt不可逆加密,自動(dòng)加鹽,每次加密結(jié)果不同,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04
  • Java中如何給List進(jìn)行排序(這7種方法輕松實(shí)現(xiàn))

    Java中如何給List進(jìn)行排序(這7種方法輕松實(shí)現(xiàn))

    在Java項(xiàng)目中可能會(huì)遇到給出一些條件,將List元素按照給定條件進(jìn)行排序的情況,這篇文章主要給大家介紹了關(guān)于Java中如何給List進(jìn)行排序的相關(guān)資料,通過(guò)文中介紹的這7種方法可以輕松實(shí)現(xiàn),需要的朋友可以參考下
    2023-10-10
  • 深入理解Java線(xiàn)程池從設(shè)計(jì)思想到源碼解讀

    深入理解Java線(xiàn)程池從設(shè)計(jì)思想到源碼解讀

    這篇文章主要介紹了深入理解Java線(xiàn)程池從設(shè)計(jì)思想到源碼解讀,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • spring-boot https證書(shū)雙向認(rèn)證配置的實(shí)現(xiàn)

    spring-boot https證書(shū)雙向認(rèn)證配置的實(shí)現(xiàn)

    本文詳細(xì)介紹SpringBoot項(xiàng)目中配置自簽名CA證書(shū)、簽發(fā)服務(wù)端和客戶(hù)端證書(shū),生成PKCS12格式的證書(shū),及設(shè)置SSL/TLS配置,實(shí)現(xiàn)雙向認(rèn)證,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-08-08
  • JAVA使用ElasticSearch查詢(xún)in和not in的實(shí)現(xiàn)方式

    JAVA使用ElasticSearch查詢(xún)in和not in的實(shí)現(xiàn)方式

    今天小編就為大家分享一篇關(guān)于JAVA使用Elasticsearch查詢(xún)in和not in的實(shí)現(xiàn)方式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • springboot請(qǐng)求找不到路徑異常的問(wèn)題

    springboot請(qǐng)求找不到路徑異常的問(wèn)題

    這篇文章主要介紹了springboot請(qǐng)求找不到路徑異常的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評(píng)論

富宁县| 古蔺县| 石渠县| 酒泉市| 海城市| 平乡县| 云安县| 云安县| 兖州市| 湛江市| 谷城县| 石家庄市| 宜兰市| 米脂县| 木兰县| 英吉沙县| 宕昌县| 定州市| 曲沃县| 临汾市| 建德市| 甘孜县| 廉江市| 浏阳市| 彰化市| 曲靖市| 华蓥市| 平舆县| 辉县市| 广昌县| 东至县| 锡林浩特市| 浠水县| 屯留县| 柯坪县| 保靖县| 杭州市| 大同县| 临澧县| 赤城县| 鄢陵县|