序列化与反序列化(ObjectOutputStream、ObjectInputStream)
序列化:
把对象以流的方式,写入到文件中保存,也叫对象的序列化
对象中包含的不仅仅是字符,所以要使用字节
ObjectOutputStream:对象的序列化流-->writeObject(对象)
反序列化:
把文件中保存的对象,以流的方式读取出来,叫做读对象,也叫对象的反序列化
读取的文件包存的都是字节,使用字节流 --->readObject();
接收时为对象 ,要用Object类来接收。
ObjectOutputStream类
java.io.ObjectOutputStream extends OutputStream
ObjectOutputStream:对象的序列化流
作用:把对象以流的方式写入到文件中保存
构造方法:
public ObjectOutputStream(OutputStream out)
特有的成员方法:
public final void writeObject(Object obj):将指定对象写入ObjectOutputStream
使用步骤:
1.创建ObjectOutputStream对象,构造方法中传递字节输出流对象
2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
3.释放资源
注意:
序列化和反序列化的时候,会出现NotSerializableException没有序列化异常
要写的类对象必须实现java.io.Serializable接口以启动其序列化功能。为事项该序列化接口,将无法使其序列化与反序列化
Serializable接口也叫标记型接口(改接口里面什么都没有,只进行一个标记作用)
要进行序列化和反序列化的类必须实现java.io.Serializable接口,就会给类添加一个标记
当我们进行序列化和反序列化时,就检测是否有该标记
有:序列化或反序列化
没有:抛出NotSerializableException异常
package iotest.testObjectIO; import java.io.Serializable; class Person implements Serializable {//必须实现Serializable接口,否则会抛出NotSerializableException异常 String name;// 被transient修饰的成员变量,不能被序列化,这儿如果加transient,读到的对象名为null public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package iotest.testObjectIO; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; public class TestObjectOutputStream { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\iotest\\testObjectIO\\a.txt")); Person person = new Person("小明"); oos.writeObject(person); oos.close(); } }
ObjectInputStream类:
java.io.ObjectInputStream extends InputStream
ObjectInputStream:对象的反序列化流
作用:将文件中保存的对象以流的形式读取出来,从而进行使用
构造方法:
public ObjectInputStream(InputStream in)
特有的成员方法:
public final Object readObject():将文件中存储的对象读取出来,并返回Object对象(这儿可强转对象)
使用步骤:
1.创建ObjectInputStream对象,构造方法中传递字节输入流对象
2.使用ObjectInputStream对象中的方法readObject(),把文件中的对象读取出来
3.释放资源
4.使用读取出来的对象(可以使用将Object对象强转为具体的类对象)
反序列化的前提:
1.类必须实现Serializable
2.必须存在类的写入文件
package iotest.testObjectIO; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class TestObjectInputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\iotest\\testObjectIO\\a.txt")); Person person = (Person) ois.readObject();//将返回的Object对象强转为person对象 System.out.println(person.getName()); ois.close(); } }
transient关键字:瞬态关键字
被transient修饰的成员变量,不能被序列化
序列号冲突异常InvalidClassException(Serializable接口中)
练习:序列化集合
package iotest.testObjectIO; import java.io.*; import java.util.ArrayList; //练习:序列化集合 //当我们在文件中存储多个对象,可以把文件存储到一个集合中,对集合进行序列化与反序列化 public class ObjectList { public static void main(String[] args) throws IOException, ClassNotFoundException { ArrayList<Person> arrayList = new ArrayList<>(); arrayList.add(new Person("小明")); arrayList.add(new Person("小红")); arrayList.add(new Person("李华")); arrayList.add(new Person("张三")); arrayList.add(new Person("李四")); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("src\\iotest\\testObjectIO\\b.txt")); objectOutputStream.writeObject(arrayList); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("src\\iotest\\testObjectIO\\b.txt")); ArrayList<Person> arrayList1 = (ArrayList<Person>) objectInputStream.readObject(); for (Person person : arrayList1) { System.out.println(person.getName()); } objectInputStream.close(); objectOutputStream.close(); } }