Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。
为什么需要序列化与反序列化 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
ObjectInputStream
public class ObjectInputStreamextends InputStreamimplements ObjectInput, ObjectStreamConstants
ObjectInputStream 对使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。
readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。
例如,要从由 ObjectOutputStream 中的示例写入的流读取:
FileInputStream fis = new FileInputStream("t.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);
int i = ois.readInt();
String today = (String) ois.readObject();
Date date = (Date) ois.readObject();
ois.close();
构造方法:
ObjectInputStream
public ObjectInputStream(InputStream in)
throws IOException创建从指定 InputStream 读取的 ObjectInputStream。从流读取序列化头部并予以验证。在对应的 ObjectOutputStream 写入并刷新头部之前,此构造方法将阻塞。
如果安装了安全管理器,则重写 ObjectInputStream.readFields 或 ObjectInputStream.readUnshared 方法的子类的构造方法直接或间接调用此构造方法时,它将对 "enableSubclassImplementation" SerializablePermission 进行检查。
参数:
in - 要从中读取的输入流
抛出:
StreamCorruptedException - 如果流的头部不正确
IOException - 如果读取流头部时发生 I/O 错误
SecurityException - 如果不受信任的子类非法重写安全敏感的方法
NullPointerException - 如果 in 为 null
另请参见:
ObjectInputStream(), readFields(), ObjectOutputStream.ObjectOutputStream(OutputStream)
ObjectOutputStream
public class ObjectOutputStreamextends OutputStreamimplements ObjectOutput, ObjectStreamConstants
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
例如,要写入可通过 ObjectInputStream 中的示例读取的对象,请执行以下操作:
FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());
oos.close();
构造方法:
ObjectOutputStream
public ObjectOutputStream(OutputStream out)
throws IOException创建写入指定 OutputStream 的 ObjectOutputStream。此构造方法将序列化流部分写入底层流;调用者可以通过立即刷新流,确保在读取头部时,用于接收 ObjectInputStreams 构造方法不会阻塞。
如果安装了安全管理器,则在通过重写 ObjectOutputStream.putFields 或 ObjectOutputStream.writeUnshared 方法的子类的构造方法来直接或间接调用此构造方法时,它将对 "enableSubclassImplementation" SerializablePermission 进行检查。
参数:
out - 要写入数据的输出流
抛出:
IOException - 如果在写入流部分时发生 I/O 错误
SecurityException - 如果不受信任的子类非法重写安全敏感方法
NullPointerException - 如果 out 为 null
简单实例: 先定义一个学生类:
public class Student implements Serializable{
private String name;
private char sex;
private int year;
private double gpa;
public Student(String name,char sex,int year,double gpa) {
this.gpa = gpa;
this.name = name;
this.sex = sex;
this.year = year;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public double getGpa() {
return gpa;
}
public void setGpa(double gpa) {
this.gpa = gpa;
}
}
再把学生类序列化到txt文件中,并且反序列化读取出来,输出在控制台:
public class UseStudent {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student student = new Student("LIN",'a',2015, 12);
File file = new File("student.txt");
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(student);
objectOutputStream.flush();
objectOutputStream.close();
fileOutputStream.close();
FileInputStream fileInputStream = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Student student1 = (Student) objectInputStream.readObject();
System.out.println(student1.getName());
System.out.println(student1.getSex());
System.out.println(student1.getYear());
System.out.println(student1.getGpa());
objectInputStream.close();
fileInputStream.close();
}
}