对象的序列化:
把对象以流的方式,写入到文件中保存,叫写对象,也叫对象的序列化。
对象的反序列化:
把文件中保存的对象,以流的方式读取出来,叫对象反序列化。
对象的类必须要实现java.io.Serializable接口以启动其序列化功能,未实现此接口的类将无法进行序列化或反序列化
Serializable接口也叫标记性接口(它就是一个空白的接口)
要进行序列化和反序列化的类必须实现Seriazable接口就会给类添加一个标记
当我们进行序列化和反序列化的时候,就会检测类中是否有这个标记
有:就可以序列化和反序列化
没有:就会抛出NotSeriazableException异常
ObjectOutputStream(序列化流):
构造 方法:
ObjectOutputStream(OutputStream out)
参数:
outputStream out:字节输出流,指定序列化对象存放的文件
特有的成员方法:
void writeObject(Object obj),将指定的对象写入指定的文件中
eg:
package io.serialized_demo.test;
import 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;
}
}
package io.serialized_demo.test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Test {
public static void main(String[] args) throws IOException {
mother();
}
private static void mother() throws IOException {
//创建序列化流,并为它指定文件的目的地
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("person.txt"));
//创建一个对象并进行序列化
oos.writeObject(new Person("小明",18));
//刷新流
oos.flush();
//关闭流
oos.close();
}
}
对象反序列化流(ObjectInputStream)
作用:把文件中保存的对象,以流的方式读取出来使用
构造方法:
ObjectInputStream(InputStream in)创建从指定的文件中读取
特有方法:
Object readObject() 从ObjectInputStream流中转换为一个Object对象
eg:
package io.serialized_demo.test;
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// mother();
mother2();
}
private static void mother2() throws IOException, ClassNotFoundException {
//创建一个反序列化的流,并指定要读取的文件
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("person.txt"));
//把文件的内存,解析为一个Object对象
Object o = ois.readObject();
//使用解析的对象
if(o instanceof Person){
Person p=(Person)o;
System.out.println(p.getName()+" "+p.getAge());
}
//关闭资源
ois.close();
}
private static void mother() throws IOException {
//创建序列化流,并为它指定文件的目的地
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("person.txt"));
//创建一个对象并进行序列化
oos.writeObject(new Person("小明",18));
//刷新流
oos.flush();
//关闭流
oos.close();
}
}
反序列化的前提:
1,类必须实现Seriazable接口
2,必须存在类对应的class文件
transient关键字(瞬态关键字)
被static修饰的成员变量不能被序列化,因为序列化是对象的内容
被transient修饰的成员变量,也是不能被序列化的
注意:当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败抛出一个InvalidClassException异常
编译器(javac.exe)会把Person.java文件编译生成Person.class文件。Person类实现了Serializable接口,就会根据类的定义给Person.class,添加一个序列号
为解决这个问题我们可以在要进行序列化的类中显式声明serialVersionUID
static final long serialVersionUID=42L;