序列化:把對象寫入到流中java
反序列化:把對象從流中讀取出來數據庫
public class Student implements Serializable{ private static final long serialVersionUID = 2992794326818594180L; private String name; private int age; //省略constructor、setter、getter、toString } @Test public void test1() throws Exception { Student s1=new Student("tom",20); System.out.println(s1); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s1); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); } 輸出: Student [name=tom, age=20] Student [name=tom, age=20]
若是序列化對象的非基本數據類型屬性沒有實現Serialize接口,會拋出NotSerializableException異常網絡
public class Student implements Serializable{ private static final long serialVersionUID = 2992794326818594180L; private String name; private int age; private School school; //省略constructor、setter、getter、toString } class School{ private String name; //省略constructor、setter、getter、toString } public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { Student s1=new Student("tom",20,new School("xw")); System.out.println(s1); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s1); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); } 輸出: java.io.NotSerializableException: com.moyuduo.analyze.School
這種方式比實現Serializable接口略複雜,可是能夠實現更加複雜的控制,由於實現Externaliable接口重寫方法須要咱們本身指定序列化規則(能夠對序列化進行加密產生字節)和反序列化規則(序列化規則的逆過程)ide
實現Externaliable接口方式比實現Serializable接口方式的效率高ui
public class Student implements Externalizable{ private String name; private int age; private School school; public Student() {//必須加無參構造器 System.out.println("Student無參構造器"); } //省略有參constructor、setter、getter、toString @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(new StringBuffer(this.name).reverse().toString()); out.writeInt(this.age); out.writeObject(this.school); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { this.name=new StringBuffer((String)in.readObject()).reverse().toString(); this.age=in.readInt(); this.school=(School)in.readObject(); } } class School implements Externalizable{ private String name; public School() { System.out.println("School無參構造器"); } //省略有參constructor、setter、getter、toString @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(new StringBuffer(this.name).reverse().toString()); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { this.name=new StringBuffer((String)in.readObject()).reverse().toString(); } } public static void main(String[] args) throws Exception { Student s1=new Student("tom",20,new School("xh")); System.out.println(s1); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s1); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); ois.close(); } 輸出: Student [name=tom, age=20, school=School [name=xh]] Student無參構造器 School無參構造器 Student [name=tom, age=20, school=School [name=xh]]
被transient關鍵字修飾的屬性,在對象序列化時不會序列化,並且反序列化獲得的該屬性值是默認值this
public class Student implements Serializable{ private static final long serialVersionUID = 1L; private String name; private transient int age; //省略constructor、setter、getter、toString } public static void main(String[] args) throws Exception{ Student s=new Student("tom",20); System.out.println(s); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); ois.close(); } 輸出: Student [name=tom, age=20] Student [name=tom, age=0]
private void writeObject(java.io.ObjectOutputStream out) throws IOException; private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;
writeObject方法序列化須要的屬性加密
public class Student implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; //省略constructor、setter、getter、toString private void writeObject(ObjectOutputStream out) throws IOException{ out.writeObject(this.name); } private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{ this.name=(String)in.readObject(); } } public static void main(String[] args) throws Exception{ Student s=new Student("tom",20); System.out.println(s); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); ois.close(); } 輸出: Student [name=tom, age=20] Student [name=tom, age=0]
在對象進行序列化時,被static修飾的屬性並不會進行序列化code
public class Student implements Serializable{ private static final long serialVersionUID = 1L; private String name; public static int age; //省略constructor、setter、getter、toString } public static void main(String[] args) throws Exception{ Student s=new Student("tom"); Student.age=20; System.out.println(s); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s); oos.close(); Student.age=30; ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); ois.close(); } 輸出: Student [name=tom,age=20] Student [name=tom,age=30]
能夠看到Student的static屬性age並無被序列化輸出對象
serialVersionUID是用於肯定版本信息的,若是不指定JVM會根據類信息自動生成一個,JVM會根據兩個serialVersionUID判斷是不是同一個類,若是serialVersionUID不一致,會拋出InvalidClassException異常接口
通常建議顯式指定serialVersionUID,若是類中添加了新的屬性,而想進行向下兼容的話,能夠不改變serialVersionUID,那麼反序列化後新添加的屬性就是默認值
若是刪除了類的屬性,就須要修改serialVersionUID
public class Student implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; //省略constructor、setter、getter、toString } //把對象寫出去 @Test public void test4() throws IOException { Student s=new Student("tom",20); System.out.println(s); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:/student.txt")); oos.writeObject(s); oos.close(); } //刪除Student的age屬性,並修改serialVersionUID public class Student implements Serializable{ private static final long serialVersionUID = 2L; private String name; //省略constructor、setter、getter、toString } //讀取對象 public static void main(String[] args) throws Exception{ Student s=new Student("tom"); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:/student.txt")); Student s2=(Student)ois.readObject(); System.out.println(s2); ois.close(); } 輸出: Exception in thread "main" java.io.InvalidClassException: com.moyuduo.analyze.Student; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2