1、序列化概述
在开发中,经常需要将对象的信息保存到磁盘中,便于以后检索。序列化提供了轻松实现这个目标的快捷方法。
简单的说,序列化就是将对象的状态存储到特定存储介质的过程,也就是将对象状态转换为可保存或传输格式的过程。在序列化过程中,会将对象的公有成员,私有成员包括类名,转换为字节流,然后再把字节流写入数据流,存储到存储介质中,这里说的存储介质通常指的是文件。
使用序列化的意义在于将Java对象序列化后,可以将其转换为字节序列,这些字节序列可以被保存到磁盘中,也可以借助网络进行传输,同时序列化后的对象保存的是二进制状态,这样实现了平台无关性,即可以把Windows操作系统中实现序列化的一个对象,传输到UNIX操作系统的机器上,通过反序列化得到对象,而无需担心数据因为平台问题显示异常。
2、使用序列化保存对象信息
序列化机制允许将实现序列化的的Java对象转换为字节序列,这个过程需要借助于IO流来实现。Java 中,只有实现了java.io.Serializable接口的类的对象才能被序列化,Serializable表示可串行的,可序列化的,所以,对象序列化在某些文献上也被称为串行化。JDK类库中有些类,如String类,包装类和Date类等都实现了Serializable接口。
对象序列化的步骤:
a、创建一个对象输出流(ObjectOutputStream),它可以包装一个其他类型的输出流,如文件输出流(FileOutputStream)。
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:\\myTest\\Test.txt"));
b、通过对象输出流的writeObject()方法写对象,也就是输出可序列化对象。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
public class WriteObjectTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
//本代码直接抛出异常,没有处理
Date date = new Date();
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("C:\\Users\\zhangwendi\\Desktop\\Test.txt"));
oos.writeObject(date);
if (oos != null)
oos.close();
}
}
3、使用反序列化获取对象信息
序列化是将对象的状态信息保存到存储介质中,
反序列化是从特定的存储介质中将数据重新构建对象的过程。
通过反序列化,可以将存储在文件上的对象信息读取,然后重新构建为对象。
步骤:
a、创建一个对象输入流(ObjectInputStream),它可以包装一个其他类型的输入流,如文件输入流FileInputStream
b、通过对象输入流的readObject()方法读取对象,该方法返回一个Object类型的对象,如果程序知道该Java对象的类型,则可以将该对象强制转换为其真实的类型。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ReadObjectTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// 本代码直接抛出异常,没有处理
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\zhangwendi\\Desktop\\Test.txt"));
Date d = (Date) (ois.readObject());
SimpleDateFormat dateformat = new SimpleDateFormat("YYYY年MM月dd日HH:mm:ss");
System.out.println(dateformat.format(d));
System.out.println(d);
ois.close();
}
}
通常,对象中的所有属性都会被序列化,但是对于一些比较敏感的信息,如用户的密码,一旦序列化后,人们完全可以通过读取文件或拦截网络传输数据的方式,获得这些信息。因此,出于对安全的考虑,某些属性应该被限制序列化。解决得方法是,使用transient修饰。
注意:
a、如果向文件中使用序列化机制写入多个对象,那么反序列化恢复对象时,必须按照写入的顺序读取。
b、如果一个可序列化的类,有多个父类(包括直接或间接父类),则这些父类要么也是可序列化的,要么有无参数的构造器。否则会抛出异常。
4、对象引用的序列化
如果一个类的成员包括其他类的对象时,如班级类中包含学生类型的对象,那么当要序列化班级对象时,则必须保证班级类和学生类都是可序列化的。即当需要序列化某个特定对象,那么它的各个成员对象也必须是可序列化的。
序列化的算法规则如下:
所有保存到磁盘中的对象都有一个序列号。
当程序试图序列化一个对象时,将会检查是否已经被序列化,只有序列化后的对象才能被转换为字节序列输出。
如果对象已经被序列化,则程序直接输出一个序列化编号,而不再重新序列化。