一、对象序列化机制
序列化机制允许将实现序列化的Java对象转换为字节序列,这些字节序列可以被保存在磁盘上或通过网络传输,以备以后重新恢复原来的对象;
序列化机制使得对象可以脱离程序的运行而独立存在;
二、对象序列化与反序列化
对象的序列化(Serialize):指将一个Java对象写入IO流中;
对象的反反序列化(Deserialize):则指从IO流中恢复该Java对象;
三、序列化实现
如果需要让某个对象可以支持序列化机制,必须让它的类是可序列化(serializable),为了让某个类可序列化的,必须实现如下两个接口之一:
Serializable:标记接口,无须实现任何方法,只是表明该类是可序列化的;
Externalizable:
所有在网络上传输的对象都应该是可序列化的,否则将会出现异常;所有需要保存到磁盘里的对象的类都必须可序列化;
通常建议:程序创建的每个JavaBean类都实现Serializable;
四、使用对象流实现序列化
将某个对象保存到磁盘上或者通过网络传输:
1.创建一个ObjectOutputStream;
2.调用ObjectOutputStream对象的writeObject方法输出可序列化对象;
Person.java文件
public class Person implements Serializable { private String name; private int age; //注意:此处没有提供无参数的构造方法,当程序调用的时候,没有看见调用构造器,这表明反序列化无须通过构造器来初始化Java对象; public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }WriteObject.java文件
public class WriteObject { public static void main(String[] args) { ObjectOutputStream oos = null; try { //1.创建一个ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")); Person per = new Person("孙悟空", 500); //2.将per对象写入输入流 oos.writeObject(per); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(oos != null){ oos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
程序希望从二进制流中恢复Java对象:
1.创建一个ObjectInputSteam;
2.调用ObjectInputStream的readObject方法读取流中的对象,该方法返回一个Object类型的Java对象,如果程序知道该Java对象的类型,则可以将该对象转换成其真实类型;
public class ReadObject { public static void main(String[] args) { ObjectInputStream ois = null; try { //1.创建一个ObjectInputStream输入流 ois = new ObjectInputStream(new FileInputStream("object.txt")); //2.从输入流中读取一个Java对象,并将其强制类型转换为Person对象 Person p = (Person) ois.readObject(); System.out.println("名字为:" + p.getName() + "\n年龄为:" + p.getAge()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally{ try { if (ois == null) { ois.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
输出:
名字为:孙悟空
年龄为:500
注意:反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供Java对象所属的class文件,否则会引发ClassNotFoundException异常;
如果我们向文件中使用序列化机制写入了多个Java对象,使用反序列化机制恢复对象必须按照实际写入的顺序读取。
当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参的构造器,要么也是可序列化的—否则反序列化将抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类定义的Field值不会被序列化到二进制流中;
五、对象引用的序列化
如果某个类的Field类型不是基本类型或者String类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则有用该类型的Field的类也是不可序列化的;
Teacher.java文件