將對象序列化和反序列化


對象在java中是以堆的方式存儲。有時候需要復制對象或者存儲對象,而不是對象的引用,這時候就需要用的對象的序列化和反序列化。

1.序列化

 Java序列化是指把Java對象轉換為字節序列的過程;而Java反序列化是指把字節序列恢復為Java對象的過程。

很詳細的博客Java中的序列化Serialable高級詳解

簡單的來說大概有幾點注意事項:

  1. 對象要實現了Serializable 接口
  2. 如果序列化和反序列化的serialVersionUID不同則反序列化失敗,因為java是通過這個來進行序列化驗證的。因此最好還是要定義serialVersionUID 
  3. 序列化保存的是對象的狀態,靜態變量屬於類的狀態,因此 序列化並不保存靜態變量
  4. Transient 關鍵字的作用是控制變量的序列化,在變量聲明前加上該關鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient 變量的值被設為初始值,如 int 型的是 0,對象型的是 null
  5. 一個子類實現了 Serializable 接口,它的父類都沒有實現 Serializable 接口,序列化該子類對象,然后反序列化后輸出父類定義的某變量的數值,該變量數值與序列化時的數值不同。反序列化時,為了構造父對象,只能調用父類的無參構造函數作為默認的父對象。

2.實例

 1 /**
 2  * Copyright &copy; 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 3  */
 4 package com.thinkgem.jeesite.common.utils;
 5 
 6 import java.io.ByteArrayInputStream;
 7 import java.io.ByteArrayOutputStream;
 8 import java.io.ObjectInputStream;
 9 import java.io.ObjectOutputStream;
10 import java.lang.reflect.Method;
11 
12 import org.apache.commons.lang3.StringUtils;
13 
14 /**
15  * 對象操作工具類, 繼承org.apache.commons.lang3.ObjectUtils類
16  * @author ThinkGem
17  * @version 2014-6-29
18  */
19 public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
20 
21     /**
22      * 注解到對象復制,只復制能匹配上的方法。
23      * @param annotation
24      * @param object
25      */
26     public static void annotationToObject(Object annotation, Object object){
27         if (annotation != null){
28             Class<?> annotationClass = annotation.getClass();
29             Class<?> objectClass = object.getClass();
30             for (Method m : objectClass.getMethods()){
31                 if (StringUtils.startsWith(m.getName(), "set")){
32                     try {
33                         String s = StringUtils.uncapitalize(StringUtils.substring(m.getName(), 3));
34                         Object obj = annotationClass.getMethod(s).invoke(annotation);
35                         if (obj != null && !"".equals(obj.toString())){
36                             if (object == null){
37                                 object = objectClass.newInstance();
38                             }
39                             m.invoke(object, obj);
40                         }
41                     } catch (Exception e) {
42                         // 忽略所有設置失敗方法
43                     }
44                 }
45             }
46         }
47     }
48     
49     /**
50      * 序列化對象
51      * @param object
52      * @return
53      */
54     public static byte[] serialize(Object object) {
55         ObjectOutputStream oos = null;
56         ByteArrayOutputStream baos = null;
57         try {
58             if (object != null){
59                 baos = new ByteArrayOutputStream();
60                 oos = new ObjectOutputStream(baos);
61                 oos.writeObject(object);
62                 return baos.toByteArray();
63             }
64         } catch (Exception e) {
65             e.printStackTrace();
66         }
67         return null;
68     }
69 
70     /**
71      * 反序列化對象
72      * @param bytes
73      * @return
74      */
75     public static Object unserialize(byte[] bytes) {
76         ByteArrayInputStream bais = null;
77         try {
78             if (bytes != null && bytes.length > 0){
79                 bais = new ByteArrayInputStream(bytes);
80                 ObjectInputStream ois = new ObjectInputStream(bais);
81                 return ois.readObject();
82             }
83         } catch (Exception e) {
84             e.printStackTrace();
85         }
86         return null;
87     }
88 }

java.io.ObjectOutputStream:表示對象輸出流

它的writeObject(Object obj)方法可以對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中。

java.io.ObjectInputStream:表示對象輸入流

它的readObject()方法源輸入流中讀取字節序列,再把它們反序列化成為一個對象,並將其返回。

本示例中,將對象序列化為byte數組,首先創造一個ByteArrayOutputStream字節數組輸出流,表示輸出。然后使用ObjectOutputStream(字節數組輸出流)來構造一個對象輸出流,表示將對象輸出到字節數組輸出流中。最后通過 oos.writeObject(object);將object寫入字節數組輸出流,再轉換為字節數組。反序列則相反。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM