先上代碼java
package com.yuan.Serial; public enum Gender { MALE, FEMALE }
而後是須要序列化Person對象數組
package com.yuan.Serial; import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; transient private Integer age; //transient 關鍵字表面該字段不被序列化 private Gender gender; public Person() { System.out.println("none-arg constructor"); } public Person(String name, Integer age, Gender gender) { System.out.println("arg constructor"); this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; } @Override public String toString() { return "[" + name + ", " + age + ", " + gender + "]"; } }
package com.yuan.Serial; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SimpleSerial { public static void main(String[] args) throws Exception { File file = new File("C:\\Users\\Oscar\\Desktop\\123.txt"); ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file)); Person person = new Person("John", 101, Gender.MALE); oout.writeObject(person); oout.close(); ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file)); Object newPerson = oin.readObject(); // 沒有強制轉換到Person類型 oin.close(); System.out.println(newPerson); } }
使用Java對象序列化,在保存對象時,會把其狀態保存爲一組字節,在將來,再將這些字節組裝成對象。必須注意地是,對象序列化保存的是對象的"狀態",即它的成員變量。由此可知,對象序列化不會關注類中的靜態變量。ide
爲何一個類實現了Serializable接口,它就能夠被序列化呢?在上節的示例中,使用ObjectOutputStream來持久化對象,在該類中有以下代碼:測試
private void writeObject0(Object obj, boolean unshared) throws IOException { ... if (obj instanceof String) { writeString((String) obj, unshared); } else if (cl.isArray()) { writeArray(obj, desc, unshared); } else if (obj instanceof Enum) { writeEnum((Enum) obj, desc, unshared); } else if (obj instanceof Serializable) { writeOrdinaryObject(obj, desc, unshared); } else { if (extendedDebugInfo) { throw new NotSerializableException(cl.getName() + "\n" + debugInfoStack.toString()); } else { throw new NotSerializableException(cl.getName()); } } ... }
從上述代碼可知,若是被寫對象的類型是String,或數組,或Enum,或Serializable,那麼就能夠對該對象進行序列化,不然將拋出NotSerializableException。this
若是僅僅只是讓某個類實現Serializable接口,而沒有其它任何處理的話,則就是使用默認序列化機制。使用默認機制,在序列化對象時,不只會序列化當前對象自己,還會對該對象引用的其它對象也進行序列化,一樣地,這些其它對象引用的另外對象也將被序列化,以此類推。因此,若是一個對象包含的成員變量是容器類對象,而這些容器所含有的元素也是容器類對象,那麼這個序列化的過程就會較複雜,開銷也較大。spa
在現實應用中,有些時候不能使用默認序列化機制。好比,但願在序列化過程當中忽略掉敏感數據,或者簡化序列化過程。下面將介紹若干影響序列化的方法。debug
transient關鍵字code
當某個字段被聲明爲transient後,默認序列化機制就會忽略該字段。此處將Person類中的age字段聲明爲transient,以下所示,對象
public class Person implements Serializable { ... transient private Integer age = null; ... }
再執行SimpleSerial應用程序,會有以下輸出:接口
arg constructor
[John, null, MALE]
可見,age字段未被序列化。