1)流序列化對象ObjectOutputStream調用writerObject寫出序列化對象,ObjectInputStream調用readObject讀取序列化對象,序列化的對象必須要實現Serializable介面,該介面沒有任何需要待實現的方法,只需繼承即可。序列化之前的對象和序列化之後的對 ...
1)流序列化對象ObjectOutputStream調用writerObject寫出序列化對象,ObjectInputStream調用readObject讀取序列化對象,序列化的對象必須要實現Serializable介面,該介面沒有任何需要待實現的方法,只需繼承即可。序列化之前的對象和序列化之後的對象是兩個不同的對象,兩者不是相等的。
序列化代碼樣例:
//寫出序列化 String path="G:\\obj.txt"; ObjectOutputStream stream=new ObjectOutputStream(new FileOutputStream(path)); stream.writeObject(student); stream.close(); // 讀取序列化 ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream(path)); Student student2=(Student)inputStream.readObject(); inputStream.close();
在序列化過程中,某些域(屬性)不想被序列化,可以使用transient標記不被序列化(方法不適用transient),不可序列化的類作為一個屬性表示的話一定要加上transient不然會報NotSerializableException。
例子:
private transient String _date;
方法標記transient報錯 必須去掉transient標記。
2)使用Externalizable介面可以定製自己的序列化機制,此介面有兩個公開的可重寫的方法readExternal和writeExternal
代碼樣例:
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { // TODO 自動生成的方法存根 ExternalDemo demo = new ExternalDemo(); demo.setName("zhangsan"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream( Paths.get("G:\\", "ExternalDemo.dat").toFile())); demo.writeExternal(out); ObjectInputStream in = new ObjectInputStream(new FileInputStream(Paths .get("G:\\", "ExternalDemo.dat").toFile())); demo.readExternal(in); System.out.println(demo.getName()); }
public class ExternalDemo implements Externalizable { private String _name; public String getName() { return _name; } public void setName(String name) { _name = name; } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // TODO 自動生成的方法存根 _name = (String) in.readObject(); } @Override public void writeExternal(ObjectOutput out) throws IOException { // TODO 自動生成的方法存根 out.writeObject(_name); } }
3)序列化單例和類型安全的枚舉
上面已介紹過普通的序列化寫出和讀取的對象是兩個不同的對象,而對於單例來說要求寫出和讀取的對象是同一個對象,這就需要寫一個方法來實現readResolve()。舉一個例子來說明:
public class Orientation implements Serializable { private int value; private Orientation(int v) { value = v; } public static final Orientation HORIZONTAL = new Orientation(1); public static final Orientation VERTICAL = new Orientation(2); protected Orientation readResolve() { if (value==1) { return Orientation.HORIZONTAL; } else if (value==2) { return Orientation.VERTICAL; } else { return null; } } }
public static void main(String[] args) { try { // 待序列化的對象 Orientation horizontal = Orientation.HORIZONTAL; // 序列化 FileOutputStream fileOutputStream = new FileOutputStream(new File( "G:\\orientation.dat")); ObjectOutputStream outputStream = new ObjectOutputStream( fileOutputStream); outputStream.writeObject(horizontal); outputStream.close(); fileOutputStream.close(); // 反序列化 ObjectInputStream inputStream = new ObjectInputStream( new FileInputStream(new File("G:\\orientation.dat"))); Orientation horiOrientation = ((Orientation) inputStream .readObject()).readResolve(); inputStream.close(); // 校驗序列化前後的對象是否一致 System.out.println(horiOrientation == horizontal); } catch (Exception exception) { } }
第一段代碼中我們定義了一個私有變數value和兩個靜態對象HORIZONTAL,VERTICAL,當我們要序列化對象HORIZONTAL,其value=1,再次反序列化時,如果只調用inputStream的readObject方法,將返回一個新的Orientation對象;如果調用了readResolve方法,將返回序列化之前的對象HORIZONTAL,這是因為調用readResolve方法時會去校驗value的值,根據其值返回對象。