序列化是指將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。
在Java中創建的對象,只要沒有被回收就可以被復用,但是,創建的這些對象都是存在於JVM的堆內存中,JVM處於運行狀態時候,這些對象可以復用,
但是一旦JVM停止,這些對象的狀態也就丟失了。
在實際生活中,需要將對象持久化,需要的時候再重新讀取出來,通過對象序列化,可以將對象的狀態保存為字節數組,需要的時候再將字節數組反序列化為對象。
對象序列化可以很容易的在JVM中的活動對象和字節數組(流)之間轉換,廣泛用於RMI(遠程方法調用)以及網絡傳輸中。
特別注意:
a.靜態成員變量屬於類不屬於對象,所以不會參與序列化(對象序列化保存的是對象的“狀態”,也就是它的成員變量,因此序列化不會關注靜態變量)
b.用transient關鍵字標記的成員變量不參與序列化(在被反序列化后,transient 變量的值被設為初始值,如 int 型的是 0,對象型的是 null)
(1).Serializable
1 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> 2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
1 import java.io.Serializable; 2 3 public class StudentSerializable implements Serializable { 4 5 //指定serialVersionUID, 6 //因為原則上序列化后的數據中的serialVersionUID只有和當前類的serialVersionUID相同時才能被正常的反序列化 7 //最好自己指定UID或者系統生成,因為如果增加或者刪除了某些成員變量,那么系統就會重新生成hash值然后賦給UID,導致反序列化時候crash 8 private static final long serialVersionUID = 10000000000000000L; 9 10 private int Uid; 11 private String Name ; 12 13 public int getUid() { 14 return Uid; 15 } 16 public void setUid(int uid) { 17 Uid = uid; 18 } 19 public String getName() { 20 return Name; 21 } 22 public void setName(String name) { 23 Name = name; 24 } 25 @Override 26 public String toString() { 27 return "StudentSerializable [Uid=" + Uid + ", Name=" + Name + "]"; 28 } 29 30 }
1 private void DealSerializable() throws IOException { 2 // Initializes The Object 3 StudentSerializable stu = new StudentSerializable(); 4 stu.setUid(9027); 5 stu.setName("fish"); 6 7 File extDir = Environment.getExternalStorageDirectory(); 8 String filename = "tempFile.txt"; 9 File fullFilename = new File(extDir, filename); 10 11 try { 12 fullFilename.createNewFile(); 13 fullFilename.setWritable(Boolean.TRUE); 14 fullFilename.setReadable(Boolean.TRUE); 15 16 } catch (IOException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 21 // Write Obj to File 22 ObjectOutputStream oos = null; 23 try { 24 oos = new ObjectOutputStream(new FileOutputStream(fullFilename.getAbsoluteFile())); 25 oos.writeObject(stu); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } finally { 29 //oos.close(); 30 } 31 32 // Read Obj from File 33 //File file = new File("tempFile.txt"); 34 ObjectInputStream ois = null; 35 try { 36 ois = new ObjectInputStream(new FileInputStream(fullFilename.getAbsoluteFile())); 37 StudentSerializable newStu = (StudentSerializable) ois.readObject(); 38 System.out.println(newStu); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } catch (ClassNotFoundException e) { 42 e.printStackTrace(); 43 } finally { 44 //ois.close(); 45 } 46 }
在使用時,通常是和ObjectOutputStream
以及 ObjectInputStream
配套一起使用,准確的說是和ObjectOutputStream
里的writeObject ()
和 ObjectInputStream
里的 readObject ()
一起使用。writeObject()
方法是最重要的方法,用於對象序列化。如果對象包含其他對象的引用,則writeObject()方法遞歸序列化這些對象。
(2).Parcelable
1 import android.os.Parcel; 2 import android.os.Parcelable; 3 4 public class StudentParcelable implements Parcelable{ 5 6 private int Uid; 7 private String Name ; 8 9 private Book book ; 10 11 public StudentParcelable(int uid, String name) { 12 super(); 13 Uid = uid; 14 Name = name; 15 } 16 17 public int getUid() { 18 return Uid; 19 } 20 public void setUid(int uid) { 21 Uid = uid; 22 } 23 public String getName() { 24 return Name; 25 } 26 public void setName(String name) { 27 Name = name; 28 } 29 30 31 //功能:返回當前對象的內容描述,如果含有文件描述符,返回1 32 //即CONTENTS_FILE_DESCRIPTOR 33 //幾乎所有情況都會返回0 34 @Override 35 public int describeContents() { 36 // TODO Auto-generated method stub 37 return 0; 38 } 39 40 /** 41 * 序列化功能由writeToParcel完成,最終通過Parcel的一系列Write方法完成 42 */ 43 //功能:將當前對象寫入序列化結構中,其中flags標識有兩種值,0或1 44 //為1時標識當前對象需要作為返回值返回,不能立刻釋放資源,即PARCELABLE_WRITE_RETURN_VALUE 45 //不過幾乎所有情況都為0 46 @Override 47 public void writeToParcel(Parcel dest, int flags) { 48 // TODO Auto-generated method stub 49 dest.writeInt(Uid); 50 dest.writeString(Name); 51 dest.writeParcelable(book, 0); 52 } 53 54 /** 55 * 反序列化由CREATOR來完成,其內部標明了如何創建序列化對象和數組 56 * 並通過Parcel的一系列read方法來完成反序列化 57 */ 58 public StudentParcelable(Parcel source){ 59 Uid = source.readInt(); 60 Name = source.readString(); 61 62 //注意:book是一個可序列化對象,所以它的反序列化過程需要傳遞當前線程的上下文類加載器 63 //否則會報找不到類的錯誤 64 book = source.readParcelable(Thread.currentThread().getContextClassLoader()); 65 } 66 67 public static final Parcelable.Creator<StudentParcelable> CREATOR = new Parcelable.Creator<StudentParcelable>() { 68 69 //功能: 從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層。 70 @Override 71 public StudentParcelable createFromParcel(Parcel source) { 72 // TODO Auto-generated method stub 73 return new StudentParcelable(source); 74 } 75 76 //功能:創建一個類型為T,長度為size的數組,僅一句話(return new T[size])即可。方法是供外部類反序列化本類數組使用。 77 @Override 78 public StudentParcelable[] newArray(int size) { 79 // TODO Auto-generated method stub 80 return new StudentParcelable[size]; 81 } 82 }; 83 84 85 }
1 Intent intent = new Intent(this,Second.class); 2 StudentParcelable stu = new StudentParcelable(001,"fish"); 3 intent.putExtra("student", stu); 4 startActivity(intent);
1 Intent intent = getIntent(); 2 StudentParcelable stu = (StudentParcelable) intent.getParcelableExtra("student"); 3 Log.i("LOG", "student name :" + stu.getName()); 4 Log.i("LOG", "student age :" + stu.getUid());
兩者區別:
1.Serializable實現簡單,而Parcelable需要實現特殊的接口
2.Serializable將對象轉化為字節流存儲在外部設備,需要時重新生成對象(依靠反射),因為使用反射,所以會產生大量的臨時變量,從而引起頻繁的GC,相比之下Parcelable性能更高,Parcelable的效率是Serializable的十倍以上,所以在內存中傳輸時更推薦Parcelable(比如在網絡中傳輸對象或者進程間傳輸對象,還有Intent)
3.Parcelable的整個過程都在內存中進行,反序列化讀取的就是原對象,不會創建新對象。要注意的是:不能使用要將數據存儲在磁盤上(比如永久性保存對象,或者保存對象的字節序列到本地文件中),因為Parcel是為了更好的實現在IPC間傳遞對象,並不是一個通用的序列化機制,當改變任何Parcel中數據的底層實現都可能導致之前的數據不可讀取(Parcelable 是以2進制的方式寫入,嚴重依賴寫入順序),還有就是Parcelable為了效率完全沒有考慮版本間的兼容性,所以數據持久化還是要使用Serializable(比如外部設備保存對象狀態或者網絡傳輸對象)
快速解析和序列化Json對象的類庫:LoganSquare
注意:
1.如果一個類想被序列化,需要實現Serializable接口。否則將拋出NotSerializableException
異常,這是因為,在序列化操作過程中會對類型進行檢查,要求被序列化的類必須屬於Enum、Array和Serializable類型其中的任何一種,這也是為什么Serializable雖然是一個空接口,但是只要實現了該接口就能序列化和反序列化。
2.在類中增加writeObject 和 readObject 方法可以實現自定義序列化策略,雖然這倆方法不是被顯示調用,但是因為在使用ObjectOutputStream的writeObject方法和ObjectInputStream的readObject方法時,會通過反射的方式調用到它們。
參考:http://www.hollischuang.com/archives/1140#What%20Serializable%20Did