Serializable對象徹底以它存儲的二進制位爲基礎來反序列化,而沒必要調用構造器。對於一個Externalizable對象,全部的默認構造器都會被調用(包括在字段定義時的初始化),而後調用readExternal()方法來反序列化。所以,爲了正常運行, 咱們須要在writeExternal()未來自對象的重要信息寫入(你要序列化的信息), 而後用readExternal()讀取你以前序列化的對象信息。以兩段代碼爲例:java
import java.io.*; /** * Version: 3.0 * Author: pattywgm * Time: 17/7/21 下午2:53 * Desc: */ public class SerializationTest implements Serializable { private String name; private int age; public SerializationTest(){}; public SerializationTest(String name, int age){ this.name = name; this.age = age; } public String toString(){ return "Name is: "+ this.name + " and age is: " + this.age; } public static void main(String[] args){ SerializationTest serializationTest = new SerializationTest("wkl", 27); // 1) try { ObjectOutput output = new ObjectOutputStream(new FileOutputStream("se.pkl")); // 2) output.writeObject(serializationTest); ObjectInput input = new ObjectInputStream(new FileInputStream("se.pkl")); System.out.println(input.readObject().toString()); // 3) } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
上述代碼實現了Serializable接口, 1)進行對象的實例化, 2)將對象序列化到本地,保存在se.pkl文件中 3)從本地反序列化對象,並打印輸出。在此過程當中不涉及對默認構造函數的調用。函數
1 import java.io.*; 2 3 /** 4 * Version: 3.0 5 * Author: pattywgm 6 * Time: 17/7/21 下午3:02 7 * Desc: 8 */ 9 public class ExternizationalTest implements Externalizable { 10 private String name = new String("zzk"); 11 private int age; 12 13 public ExternizationalTest(){}; 14 15 public ExternizationalTest(String name, int age){ 16 this.name = name; 17 this.age = age; 18 } 19 20 21 22 public void writeExternal(ObjectOutput out) throws IOException { 23 System.out.println("Write object...."); 24 out.writeObject(this.name); 25 out.writeInt(this.age); 26 } 27 28 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 29 System.out.println("Read object...."); 30 this.name = (String)in.readObject(); 31 this.age = in.readInt(); 32 } 33 34 public String toString(){ 35 return "Name is: "+ this.name + " and age is: " + this.age; 36 } 37 38 public static void main(String[] args){ 39 ExternizationalTest externizationalTest = new ExternizationalTest("wkl", 27); // 1) 40 try { 41 ObjectOutput output = new ObjectOutputStream(new FileOutputStream("se1.pkl")); // 2) 42 output.writeObject(externizationalTest); 43 44 ObjectInput input = new ObjectInputStream(new FileInputStream("se1.pkl")); // 3) 45 System.out.println(input.readObject().toString()); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } catch (ClassNotFoundException e) { 49 e.printStackTrace(); 50 } 51 } 52 }
上述代碼實現了Externalizable接口。this
1)進行對象的實例化;spa
2)將對象序列化到本地,保存在se.pkl文件中, 此處在writeObject()後會調用writeExternal(ObjectOutput out)方法完成對象信息的序列化,即控制序列化對象的那些信息;code
3)從本地反序列化對象,並打印輸出。在此過程當中會在readObject()後先調用默認構造器,以及第10行字段初始化,而後調用readExternal(ObjectInput in)完成對象信息的反序列化。對象
在實際的應用過程當中, 對於一些敏感信息,咱們並不但願被序列化,上述代碼中雖然name, age都是private私有字段, 但經過序列化機制,外部依然能夠獲取到他們的值, 爲了隱蔽掉對象的敏感信息, 咱們能夠使用transient關鍵字修飾敏感字段,這樣在序列化對象時,將剔除對該字段的序列化。也能夠在Externalizable對象中,經過writeExternal()進行顯示序列化。以下:blog
import java.io.*; /** * Version: 3.0 * Author: pattywgm * Time: 17/7/21 下午2:53 * Desc: */ public class SerializationTest implements Serializable { private String name; private int age; private transient String password; // 該字段不會被序列化 public SerializationTest(){}; public SerializationTest(String name, int age, String password){ this.name = name; this.age = age; this.password = password; } public String toString(){ return "Name is: "+ this.name + " and age is: " + this.age + " and password is: " + this.password; } public static void main(String[] args){ SerializationTest serializationTest = new SerializationTest("wkl", 27, "123456"); try { ObjectOutput output = new ObjectOutputStream(new FileOutputStream("se.pkl")); output.writeObject(serializationTest); ObjectInput input = new ObjectInputStream(new FileInputStream("se.pkl")); System.out.println(input.readObject().toString()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
import java.io.*; /** * Version: 3.0 * Author: pattywgm * Time: 17/7/21 下午3:02 * Desc: */ public class ExternizationalTest implements Externalizable { private String name = new String("zjm"); private int age; private String password; // 該字段不會被序列化 public ExternizationalTest(){}; public ExternizationalTest(String name, int age, String password){ this.name = name; this.age = age; this.password = password; } public void writeExternal(ObjectOutput out) throws IOException { System.out.println("Write object...."); out.writeObject(this.name); out.writeInt(this.age); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Read object...."); this.name = (String)in.readObject(); this.age = in.readInt(); } public String toString(){ return "Name is: "+ this.name + " and age is: " + this.age + " and password is: " + this.password; } public static void main(String[] args){ ExternizationalTest externizationalTest = new ExternizationalTest("wkl", 27, "123456"); try { ObjectOutput output = new ObjectOutputStream(new FileOutputStream("se1.pkl")); output.writeObject(externizationalTest); ObjectInput input = new ObjectInputStream(new FileInputStream("se1.pkl")); System.out.println(input.readObject().toString()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
若是此時咱們在SerializationTest類中引用外部一個UserInfo對象,須要注意,該UserInfo對象必須是可序列化的,即實現了Serializable接口, 不然會在運行時報java.io.NotSerializableException: com.patty.jedis.demo.UserInfo錯誤。接口