對象在java中是以堆的方式存儲。有時候需要復制對象或者存儲對象,而不是對象的引用,這時候就需要用的對象的序列化和反序列化。
1.序列化
Java序列化是指把Java對象轉換為字節序列的過程;而Java反序列化是指把字節序列恢復為Java對象的過程。
很詳細的博客Java中的序列化Serialable高級詳解。
簡單的來說大概有幾點注意事項:
- 對象要實現了Serializable 接口
- 如果序列化和反序列化的serialVersionUID不同則反序列化失敗,因為java是通過這個來進行序列化驗證的。因此最好還是要定義serialVersionUID
- 序列化保存的是對象的狀態,靜態變量屬於類的狀態,因此 序列化並不保存靜態變量
- Transient 關鍵字的作用是控制變量的序列化,在變量聲明前加上該關鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient 變量的值被設為初始值,如 int 型的是 0,對象型的是 null
- 一個子類實現了 Serializable 接口,它的父類都沒有實現 Serializable 接口,序列化該子類對象,然后反序列化后輸出父類定義的某變量的數值,該變量數值與序列化時的數值不同。反序列化時,為了構造父對象,只能調用父類的無參構造函數作為默認的父對象。
2.實例
1 /** 2 * Copyright © 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寫入字節數組輸出流,再轉換為字節數組。反序列則相反。