国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Java 高級特性之使用反射實現萬能序列化

開發 后端
很多時候我們需要將一個類的實例變成二進制數據存儲或是通過網絡發送,這個過程叫序列化。

[[437080]]

很多時候我們需要將一個類的實例變成二進制數據存儲或是通過網絡發送,這個過程叫序列化。如果將二進制數據解析成位于內存中的類實例或是相關數據結構,那叫反序列化。所有的序列化算法都遵循一定的套路,例如:

  1. class A { 
  2.  
  3. public int a = 1; 
  4.  
  5. public int b = 2; 
  6.  
  7. protected B b = new B(); 
  8.  
  9. private float c = 3.0; 
  10.  

如果要序列化類A的實例,那么通常需要將變量a,b的數值對應的二進制數寫入,然后獲得類B實例序列化后的二進制數據,最后將變量c的數值的二進制數據,這里可以體會到,序列化其實有一種遞歸的性質,在序列化過程中如果遇到的是基礎類型,那么可以直接獲取其對應的二進制數據,如果遇到類實例,那么需要先序列化它,取得對應二進制數據。

而序列化過程中需要你了解對應類的定義,但如果我們不知道要序列化的對象,例如我們看不到類A的定義,我們只拿到了A對應的一個實例對象,那此時怎么序列化呢。這就需要用到java語言的反射特性,java編譯器在編譯類A時,不僅僅將它為它的各個字段分配了內存,而且還為類A的相關信息進行了設置和存儲,例如A里面有多少字段,字段的類型是int, float, stirng,還是特定類對象,這些信息都一并設置并存儲了起來,只要我們使用java反射提供的API就能獲得這些信息,從而就能對任意類實現序列化。

因此序列化的萬能套路是:

1,獲得要序列化的類實例;

2,獲得類中各個字段的屬性,類型等相關信息。

3,如果字段屬于基礎數據,那么獲得其數值的二進制數據。

4,如果對應字段是一個類實例,那么先遞歸的序列化該實例

根據以上步驟,當我們需要序列化任意一個類實例時,首先通過getClass獲得其對應的Class類實例,然后調用getDeclaredFields()接口獲得該實例所有的字段,其中包括public,protected,private,或者調用getFields()獲得類實例聲明或繼承的公有字段。在序列化中,我們不能忘了序列化當前類實例的父類,因此可以調用getSuperClass()來獲得當前實例的父類,這個過程會不斷進行直到抵達根類為止。

每個字段都會對應一個元類叫Field,通過該類相關接口能獲得字段的值。獲取字段的數據首先需要確定字段的類型,如果是Boolean類型,那么可以調用Field類的getBoolean接口獲得數據,如果是int類型,那么可以通過getInteger()接口獲得數據,如果字段是類對象,那么就得遞歸的去獲得其二進制數據,如果字段是基礎類型,那么通過調用其getString()就能獲得其數值的字符串形式。

在獲取字段類型前,我們還需要知道字段的修飾屬性,例如是public還是private,是不是static等,這些屬性通過Field類的接口getModifier()獲得,調用它會返回一個整形值,該值在相關比特位上設置1或0來表示修飾屬性。在java語法中共有11種修飾屬性,因此有11個比特位來對應,但我們不需要分析哪個比特位設置為1來獲取字段屬性,java反射提供了一個特定類Modifier,通過getModifier返回的數值可以輸入Modifier類的isPublic, isPrivate等接口來查詢字段對應的修飾屬性。

在序列化時,我們要忽略掉static屬性的字段,因此他們是寫死的,因此通過Modifier.isStatic(field.getModifier())所得結果就能進行字段的static屬性判斷??偹苤瑢τ趐rotected 或是private類型的字段,外部是不能直接讀取的,但是序列化必須要能讀取這類字段的值,要不然序列化就無法進行,Field類提供了setAccessible(true)來打破這個限制。

此外還需要考慮的一個因素是,如果字段是數組類型的情況。java反射提供了元類Array來應對,假設實例對象obj是一個數組,那么Array.getLength(obj)就能獲得數組的長度,Array.get(obj, i)就能獲得第i個元素對象。

最后我們需要考慮序列化后的文件格式,我們使用xml格式來存儲序列化的結果,例如在上面例子中,字段a在序列化后對應為”\1\“,具體的情況我們在后續代碼中慢慢來觀察。

首先我們使用IntelliJ 創建一個maven項目,由于我們需要將數據序列化成XML文件,因此需要使用JDOM接口,于是在pom.xml中添加如下依賴:

  1. <!-- https://mvnrepository.com/artifact/org.jdom/jdom --> 
  2.       <dependency> 
  3.           <groupId>org.jdom</groupId> 
  4.           <artifactId>jdom</artifactId> 
  5.           <version>2.0.2</version> 
  6.       </dependency> 

 

然后點擊一下Maven命令面板的下載按鈕下載jdom包。然后我們創建一個實現文件叫ReflectionSerilization,然后先完成一些骨架基礎:

  1. import org.jdom2.Document; 
  2. import org.jdom2.Element; 
  3. import org.jdom2.output.XMLOutputter; 
  4. import java.lang.reflect.*; 
  5. import java.util.IdentityHashMap; 
  6. import java.util.HashMap; 
  7. import java.util.List; 
  8. import java.util.Properties; 
  9. import java.util.Map; 
  10.  
  11. public class ReflectionSerialization { 
  12.     public  Document doSerilizeObject(Object objectToSerilized) throws Exception{ 
  13.         return recursiveSerilizeObject(objectToSerilized, new Document(new Element("serialized")), 
  14.                 new IdentityHashMap()); 
  15.     } 
  16.  
  17.     private  Document recursiveSerilizeObject(Object objToSerilized, Document target, Map table) throws Exception{ 
  18.         String id = Integer.toString(table.size()); //為當前序列化的對象設置id標號 
  19.         table.put(objToSerilized, id); 
  20.         Class objClass = objToSerilized.getClass(); 
  21.  
  22.         Element elem = new Element("object"); 
  23.         elem.setAttribute("class", objClass.getName()); 
  24.         elem.setAttribute("id", id); 
  25.         target.getRootElement().addContent(elem); 
  26.         /* 
  27.          判斷當前要序列化的對象是否是數組類型,如果不是,那么先遍歷該對象所有字段,然后遞歸的序列化對應字段,因為字段有可能是類對象, 
  28.          如果是數組類型,那么遍歷其中每個元素,然后針對每個元素進行序列化 
  29.          */ 
  30.         if (objClass.isArray()) { 
  31.             //TODO 
  32.         } else { 
  33.             //TODO 
  34.         } 
  35.     } 
  36.     public static void main(String[] args) { 
  37.     } 

接下來我們針對兩個TODO進行實現,如果當前要序列化的對象不是數組,那么需要遍歷其所有字段,然后序列化各個字段,如果字段是類對象類型,那么還得遞歸的對他進行處理,我們看代碼實現:

  1.  /* 
  2.          判斷當前要序列化的對象是否是數組類型,如果不是,那么先遍歷該對象所有字段,然后遞歸的序列化對應字段,因為字段有可能是類對象, 
  3.          如果是數組類型,那么遍歷其中每個元素,然后針對每個元素進行序列化 
  4.          */ 
  5.         if (objClass.isArray()) { 
  6.             handleNoArrayField(objToSerilized, objClass, target, table, elem); 
  7.         } else { 
  8.             //TODO 
  9.         } 
  10.  
  11.     private void handleNoArrayField(Object objToSeerilized, Class cls, Document target, Map table, Element parent) throws Exception { 
  12.         Field[] fields = this.iterateClassFields(cls); 
  13.         for (int i = 0; i < fields.length; i++) { 
  14.             if (!Modifier.isPublic(fields[i].getModifiers())) { 
  15.                 fields[i].setAccessible(true); //如果不是公有字段,那么需要設置它的可讀取性 
  16.             } 
  17.  
  18.             Element fElt = new Element("field"); //針對該字段插入xml元素 
  19.             fElt.setAttribute("name", fields[i].getName()); 
  20.             Class declClass = fields[i].getDeclaringClass(); //獲取字段對應的類 
  21.             fElt.setAttribute("declaringclass", declClass.getName()); 
  22.             Class fieldType = fields[i].getType(); //獲得該字段類型對應的元類 
  23.             Object child = fields[i].get(objToSeerilized); //獲得字段對應的實例對象 
  24.             if (Modifier.isTransient(fields[i].getModifiers())) { 
  25.                 child = null
  26.             } 
  27.  
  28.             fElt.addContent(extractContentFromField(fieldType, child, target, table)); 
  29.             parent.addContent(fElt); 
  30.         } 
  31.     } 
  32. private Element extractContentFromField(Class fieldType, Object child, Document target, Map table) throws Exception{ 
  33.         //將字段對應的數據抽取出來 
  34.         if (child == null) { 
  35.             return new Element("null"); 
  36.         } 
  37.         else if (!fieldType.isPrimitive()) { 
  38.             Element reference = new Element("reference"); 
  39.             if (table.containsKey(child)) { 
  40.                 reference.setText(table.get(child).toString()); //任何基礎類型都繼承自Object,他們都支持toString來將自身對應的數據進行字符串表達 
  41.             } 
  42.             else { 
  43.                 reference.setText(Integer.toString(table.size())); 
  44.                 recursiveSerilizeObject(child, target, table); //如果不是基礎類型,那么就遞歸的進行序列化 
  45.             } 
  46.         } 
  47.  
  48.     } 
  49.  
  50.     private Field[] iterateClassFields(Class cls) { 
  51.         List fieldsList = new LinkedList(); //用隊列存儲對象所有字段 
  52.         while (cls != null) { 
  53.             Field[] fields = cls.getDeclaredFields(); //獲得當前實例對應類所聲明的所有字段 
  54.             for (int i = 0; i < fields.length; i++) { 
  55.                 if (!Modifier.isStatic(fields[i].getModifiers())) { 
  56.                     fieldsList.add(fields[i]); //如果字段不是static修飾那么就加入隊列 
  57.                 } 
  58.             } 
  59.  
  60.             cls = cls.getSuperclass(); //獲取父類然后遞歸的獲取字段 
  61.         } 
  62.  
  63.         Field[] retValue = new Field[fieldsList.size()]; 
  64.         return (Field[])fieldsList.toArray(); 
  65.     } 

我們先看第一種情況的實現,首先遍歷當前實例對應類聲明的所有字段,將所有字段放入到一個隊列中然后再一一取出來進行處理,這個功能的實現就在函數iterateClassFields,然后對取出的字段進行判斷,看它是否具備public屬性,如果不具備,那么要想讀取它的內容,我們需要調用setAccessible進行設置,接下來還有判斷其是否是Transient類型,如果不是,那么就通過extractContentFromField來讀取字段包含的數據。

在extractContentFromField中,先判斷字段是否為基礎數據類型,如果是,由于基礎數據類型都實現了toString方法,于是我們可以用該方法獲得數據的字符串對應內容,然后寫入到xml文件中,如果它不是基礎類型,那么我們就調用recursiveSerilizeObject遞歸的去對他進行序列化。

 

由于內容相對燒腦,因此我們先在這里暫停,消化一下后再處理下一步,也就是應對字段是數組類型的情況。

 

責任編輯:武曉燕 來源: Coding迪斯尼
相關推薦

2011-04-02 09:04:49

Java序列化

2021-01-20 08:24:38

序列化內存對象

2017-05-26 10:15:39

Java高級特性反射

2009-03-10 13:38:01

Java序列化字節流

2022-08-06 08:41:18

序列化反序列化Hessian

2018-03-19 10:20:23

Java序列化反序列化

2013-03-11 13:55:03

JavaJSON

2009-06-14 22:01:27

Java對象序列化反序列化

2016-11-24 12:07:42

Android萬能圓角ImageView

2011-06-01 15:05:02

序列化反序列化

2009-08-24 17:14:08

C#序列化

2010-01-08 13:25:07

ibmdwXML

2011-06-01 15:18:43

Serializabl

2011-04-02 13:47:01

2011-03-04 09:25:51

Java序列化

2023-12-13 13:49:52

Python序列化模塊

2009-08-06 11:16:25

C#序列化和反序列化

2011-05-18 15:20:13

XML

2010-03-19 15:54:21

Java Socket

2023-04-06 13:47:47

點贊
收藏

51CTO技術棧公眾號

免费成年网站| 亚洲免费一区| 久久久久久久久久久久久久久久久久av| 中文字幕一区二区三区5566| 成人在线国产| 久久九九亚洲综合| 三级成人黄色影院| 日韩欧美电影一区| 老司机午夜在线| 欧美日韩亚洲不卡| 国产玉足榨精视频在线观看| 欧美日韩亚洲天堂| 涩爱av在线播放一区二区| 午夜av一区二区三区| 国产精品久久久久久精| 国产精品久久夜| 天天操天天爱天天爽| 久久你懂得1024| 日韩视频第二页| 国产亚洲午夜高清国产拍精品| 日本十八禁视频无遮挡| 成a人片国产精品| www.avtt| 99re热这里只有精品视频| 性疯狂做受xxxx高清视频| 欧美精品aⅴ在线视频| 全部孕妇毛片丰满孕妇孕| 国产精品天天看| 在线观看免费播放网址成人| 国产精品久久久久三级| 黄色成人羞羞视频| 亚洲一区二区三区自拍| 天堂av在线7| 欧美日韩精品一区二区天天拍小说| 国产爆初菊在线观看免费视频网站 | jizz一区二区三区| 亚洲精品短视频| 一二三四视频在线中文| 亚洲日韩欧美视频一区| 香蕉久久一区| 51久久精品夜色国产麻豆| 91亚洲一区| 午夜精品美女久久久久av福利| 国产在线播放一区二区三区| 伊人成色综合网| 一区二区三区不卡视频| 欧美精品hd| 日韩在线不卡视频| 成人影院在线| 午夜免费电影一区在线观看| 成人久久视频在线观看| 婷婷亚洲天堂| 欧美日韩国产综合一区二区 | 亚洲一区二区三区在线| 91在线视频| 色诱女教师一区二区三区| 日本精品影院| 国产一区二区不卡视频在线观看| 秋霞电影一区二区| 99热成人精品热久久66| 欧美日韩国产丝袜另类| 爱草tv视频在线观看992| 美日韩精品视频免费看| 97精品97| 超碰10000| 亚洲激情在线播放| 国产1区在线| 久久在线视频在线| 这里只有精品在线| 日本香蕉视频在线观看| 狠狠躁夜夜躁人人躁婷婷91| 手机在线观看av| 日本高清视频一区| 日韩国产在线观看一区| av男人的天堂网| 亚洲成人激情视频| 亚洲黄页在线观看| 日本精品免费视频| 天天操天天干天天综合网| 成人一区视频| 麻豆91蜜桃| 综合久久久久综合| 欲香欲色天天天综合和网| 91精品免费看| 99re成人在线| heyzo在线播放| 亚洲综合在线做性| 国产精品久久久久久久久免费丝袜 | 男女无套免费网站| 91精品国产福利| 亚洲免费福利一区| 国产在线无码精品| 欧美日韩国产区一| 成人羞羞在线观看网站| www.国产区| 亚洲国产精品久久久久秋霞蜜臀 | 欧美床上激情在线观看| 99精品久久| 日日噜噜噜夜夜爽爽狠狠视频| 亚洲片在线观看| 国产综合视频| 人猿泰山h版在线观看| 久久国产一区二区三区| 蜜臀a∨国产成人精品| 香蕉国产在线| 97在线视频免费| 成人免费看视频| av中文在线资源库| 97人人模人人爽人人少妇| 成人免费在线播放视频| 视频欧美精品| 国产精品无码免费专区午夜| 欧美精品一区二区三区高清aⅴ | 国产ts一区二区| 国产日韩精品久久久| 欧美特大特白屁股xxxx| 久久伊人一区| 欧洲一区二区av| 久久裸体网站| 一个人看的免费视频色| 日本成熟性欧美| 国产精品青草综合久久久久99| 美女写真久久影院| 日韩免费在线观看av| 国产视频久久久久久久| 亚洲欧美大片| h片在线播放| 欧美一级爱爱| 日韩欧美激情四射| 老司机午夜免费精品视频| 欧美激情办公室videoshd| 成人动漫视频在线观看免费| 在线观看av一区二区| 欧美日韩免费观看一区=区三区| 欧洲毛片在线| 999在线观看免费大全电视剧| 色噜噜久久综合| 一区二区亚洲| 午夜dj在线观看高清视频完整版| 另类视频在线观看+1080p| 欧美一级理论片| 精品中文字幕一区二区小辣椒| 国产欧美一区二区三区精品酒店| 加勒比成人在线| 久久久午夜视频| 精品国产电影一区| 亚洲第一毛片| 美女91在线看| 成人性生活视频免费看| 精品国产一区二区三区久久久狼| 久久综合丝袜日本网| 久久国产精品免费精品3p| 男女激情视频网站| 成人欧美视频在线| 精品美女在线播放| a美女胸又www黄视频久久| 91精品啪在线观看国产手机 | www久久久久| 精品日韩免费| 色哟哟免费在线观看 | 久久a级毛片毛片免费观看| 成人午夜激情网| 亚洲综合第一页| 国产精品久99| 欧美日韩一卡| 精品少妇一区二区| 狠狠色狠狠色综合日日91app| 中文在线免费视频| 日韩精品第1页| 久热国产精品视频| 亚洲天堂精品视频| 欧美96在线丨欧| av在线理伦电影| 18禁男女爽爽爽午夜网站免费| 91av在线免费观看| 日韩欧美国产网站| 久久草av在线| 日韩有码中文字幕在线| 国产精品影院在线| 欧美中文字幕在线观看视频| 1769国产精品| 欧美电影一区二区三区| 99久久久精品免费观看国产蜜| 视频一区在线观看| 欧美一卡二卡| 成人拍拍拍在线观看| 国产欧美日本在线| 国产一区二区三区18| 亚洲亚洲精品在线观看| 久久一二三四| 亚洲成aⅴ人片久久青草影院| 麻豆传媒视频在线观看| 日本免费一级视频| 波多野结衣一区二区三区在线观看| 日韩美一区二区三区| 国产精品三级视频| 日本不卡一区二区三区 | 成人亚洲视频| 国产精品免费播放| 亚洲这里只有精品|