一,概述
1,对象的序列化:把对象以流的方式写入到文件中保存,即写对象,对象不仅包含字符,也有字节,使用字节流ObjectOutputStream。
2,对象的反序列化:把文件中保存的对象,以流的方式读取出来,读取的文件保存的都是字节,使用字节流ObjectInputStream。
二,ObjectOutputStream
java.io.ObjectOutputStream extends OutputStream.
OutputStream:对象的序列化流。
作用:把对象以流的方式写入到文件中保存。
构造方法:
ObjectOutputStream(OutputStream out):创建写入指定OutputStream的ObjectOutputStream。
参数:
OutputStream out:字节输出流。
特有的成员方法:
void writeObject(Object obj):将指定的对象写入ObjectOutputStream。
注意:
序列化或者反序列化时,抛出NotSerializableException没有序列化异常。
类通过实现java.io.Serializable接口启用序列化功能,未实现该接口的类无法进行序列化和反序列化。
Serializable接口也叫做标记型接口,相当于给类添加了一个标记,当进行序列化和反序列化时,会检测该类是否有该接口:
有,可进行序列化和反序列化;
没有,抛出NotSerializableException异常。
public class Person implements Serializable{
......
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class DemoObjectOutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("src\\Month_05\\day5_21\\Person.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new Person("小海",25));
oos.close();
}
}
transient 关键字:如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,用transient修饰。例如:
private transient int age;打印时打印默认值0。
三,ObjectInputStream
java.io.ObjectInputStream extends InputStream.
ObjectInputStream:对象的反序列化流。
作用:把文件中保存的对象,以流的方式读取出来使用。
构造方法:
ObjectInputStream(InputStream in)
参数:
InputStream in:字节输入流。
特有的成员方法:
Object readObject():从ObjectInputStream中读取对象。该方法声明抛出ClassNotFoundException(class文件找不到异常),当不存在对象的class文件(即Person类不存在)时抛出此异常。
反序列化的前提:
1,类必须实现Serializable接口;
2,必须存在类对应的class文件。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DemoObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("src\\Month_05\\day5_21\\Person.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
ois.close();
Person p = (Person)o;
System.out.println(p.getName()+","+p.getAge());//小海,25
}
}
注意: InvalidClassException 异常,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改(修改Person类),由于序列号不一致,那么反序列化操作也会失败,抛出一个 InvalidClassException 异常。
序列号冲突异常原理图:
解决方法:
可在类当中加入序列版本号,如
private static final long serialVersionUID = 1L;
四,综合案例:序列化集合
import java.io.*;
import java.util.ArrayList;
public class DemoListSerial {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小海",21));
list.add(new Person("小军",29));
list.add(new Person("小红",20));
list.add(new Person("小凯",21));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\Month_05\\day5_21\\list.txt"));
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\Month_05\\day5_21\\list.txt"));
Object o = ois.readObject();
ArrayList<Person> list2 = (ArrayList<Person>)o;
for (Person p : list2) {
System.out.println(p);
}
ois.close();
oos.close();
/*
Person{name='小海', age=21}
Person{name='小军', age=29}
Person{name='小红', age=20}
Person{name='小凯', age=21}
*/
}
}