对象的序列化流ObjectOutputStream
- 概述
- ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
- 只有支持java.io.Serializable接口的对象才能写入流中。 每个可序列化对象的类被编码,包括类的类名和签名,对象的字段和数组的值以及从初始对象引用的任何其他对象的关闭。
- 方法writeObject用于将一个对象写入流中。 任何对象,包括字符串和数组,都是用writeObject编写的。 多个对象或原语可以写入流。 必须从对应的ObjectInputstream读取对象,其类型和写入次序相同。
- 原始数据类型也可以使用DataOutput中的适当方法写入流中。 字符串也可以使用writeUTF方法写入。
- 对象的默认序列化机制写入对象的类,类签名以及所有非瞬态和非静态字段的值。 引用其他对象(除了在瞬态或静态字段中)也会导致这些对象被写入。 使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与原始文件相同的形状。
- 以流的方式把对象写入文件中,继承OutputStream
-
构造方法
protected ObjectOutputStream() 为完全重新实现ObjectOutputStream的子类提供一种方法,不必分配刚刚被ObjectOutputStream实现使用的私有数据。 ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream。
-
成员方法
void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。 使用步骤: 1、创建一个ObjectOutputStream对象,构造方法中传递字节输出流 2、使用ObjectOutputStream对象的方法write,把对象写入到文件中 3、释放资源
/* 序列化和反序列化的时候会抛出NotSerializableException异常 类的序列化由实现java.io.Serializable接口的类启用。 不实现此接口的类将不会使任何状态序列化或反序列化。 可序列化类的所有子类型都是可序列化的。 序列化接口没有方法或字段,仅用于标识可串行化的语义。 要实现类的序列化和反序列化,必须实现Serializable接口 */ public class Person implements Serializable { private String name; private int age; public Person() { } public Person(String name, int age) { 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; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
对象的反序列化流ObjectInputStream
- 概述
-
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
-
ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。
-
ObjectInputStream确保从流中创建的图中的所有对象的类型与Java虚拟机中存在的类匹配。 根据需要使用标准机制加载类。
-
只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象。
-
方法readObject用于从流中读取对象。 应使用Java的安全铸造来获得所需的类型。 在Java中,字符串和数组是对象,在序列化过程中被视为对象。 读取时,需要将其转换为预期类型。
-
把文件中保存的对象以流的方式读取出来,继承了InputStream
-
构造方法
protected ObjectInputStream() 为完全重新实现ObjectInputStream的子类提供一种方法,不必分配刚刚被ObjectInputStream实现使用的私有数据。 ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream。
-
成员方法
Object readObject() 从ObjectInputStream读取一个对象。 使用步骤: 1、创建ObjectInputStream对象,构造方法中传入字节输入流 2、使用ObjectInputStream对象中的方法readObject方法读取保存对象的文件 3、释放资源 4、使用读取出来的对象
try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15\\src\\person.txt")); System.out.println(ois.readObject()); } catch (Exception e) { e.printStackTrace(); }
transient关键字
- static 关键字:
- 被static修饰的成员变量不能被序列化
- 静态关键字
- 静态优先于非静态加载到内存中
- transient关键字:
- 瞬态关键字
- 被 transient修饰的成员变量不能被序列化
异常处理
- InvalidClassException
/* 序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID, 它在反序列化过程中使用,以验证序列化对象的发送者和接收者是否加载了与序列化兼容的 对象的类。 如果接收者已经为具有与对应发件人类别不同的serialVersionUID的对象加 载了一个类,则反序列化将导致一个InvalidClassException 。 一个可序列化的类可以 通过声明一个名为"serialVersionUID"的字段来显式地声明它自己的serialVersionUID, 该字段必须是static,final和long类型: */ private static final long serialVersionUID =1L;
案例
- 序列化集合
public class Person implements Serializable { private static final long serialVersionUID =1L; private String name; public int age; public Person() { } public Person(String name, int age) { 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; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
ArrayList<Person> list=new ArrayList<>(); list.add(new Person("张三",18)); list.add(new Person("李四",19)); list.add(new Person("王五",20)); list.add(new Person("赵六",21)); try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day15\\src\\personlist.txt")); oos.writeObject(list); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15\\src\\personlist.txt")); Object obj=ois.readObject(); ois.close(); oos.close(); ArrayList<Person> list2= (ArrayList<Person>)obj; for (Person person : list2) { System.out.println(person); } } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }