序列化:把对象写入到流中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