对象的序列化与反序列化
1:对象的序列化就是将Object转换成byte序列,反之叫对象的反序列化。
序列化流 ObjectOutputStream 是过滤流, writeObject方法,得往文件中写
反序列化流 ObjectInputStream readObject方法,从文件中读
序列化接口(Serializable)
对象必须实现序列化接口,才能进行序列化,否则将抛出异常。这个接口没有任何方法,只是一个标准。
package com.zhao.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class StudentSerializableDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { File file=new File("demo/obj.txt"); if (!file.exists()) { file.createNewFile(); } StudentSerializableDemo demo=new StudentSerializableDemo(); demo.outputStream(file); demo.inputStream(file); } /** * 对象的序列化 * @param file * @throws IOException * @throws IOException */ public void outputStream(File file) throws IOException{ ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream(file)); Student student=new Student("1", "李四", 21); outputStream.writeObject(student); outputStream.flush(); outputStream.close(); } /** * 对象的反序列化 * @param file * @throws IOException * @throws ClassNotFoundException */ public void inputStream(File file) throws IOException, ClassNotFoundException{ ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream(file)); Student student=(Student) inputStream.readObject(); System.out.println(student); inputStream.close(); } }
2:transient
transient不会进行jvm默认的序列化,可以自己完成这个元素的序列化
package com.zhao.serializable; import java.io.Serializable; import java.util.ArrayList; import java.util.ConcurrentModificationException; public class Student implements Serializable { private String stuno; private String stuname; // transient 不会进行jvm默认的序列化,也可以自己完成这个元素的序列化 private transient int stuage; public Student() { // TODO Auto-generated constructor stub } public Student(String stuno, String stuname, int stuage) { this.stuno = stuno; this.stuname = stuname; this.stuage = stuage; } @Override public String toString() { return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage=" + stuage + "]"; } public String getStuno() { return stuno; } public void setStuno(String stuno) { this.stuno = stuno; } public String getStuname() { return stuname; } public void setStuname(String stuname) { this.stuname = stuname; } public int getStuage() { return stuage; } public void setStuage(int stuage) { this.stuage = stuage; } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { //把jvm虚拟机能默认序列化的元素进行序列化操作 s.defaultWriteObject(); //自己完成stuage的序列化 s.writeInt(stuage); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { //把jvm虚拟机能默认反序列化的元素进行反序列化操作 s.defaultReadObject(); //自己完成stuage的反序列化操作 this.stuage=s.readInt(); } }
ArrayList的源码便进行了上述操作,目的在于 对数组的有效长度进行序列化和反序列化,对数组没有数据的元素,不进行此操作,这可以提高系统效率。
3:
当父类继承Serializable接口时,所有子类都可以被序列化。
子类实现了Serializable接口,父类没有,父类中的属性不能序列化(不报错,数据会丢失),但是在子类中属性仍能正确序列化。
如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错。
在反序列化是,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错。
在反序列化是,如果serialVersionUID被修改,则反序列化会失败。