对象流
概念
用于存储和读取基本数据类型数据或对象的处理流, 可以把 Java 中的对象写入到数据源中, 也能把对象从数据源中还原回来
序列化: 用 ObjectOutputStream 类保存基本数据类型或对象的机制
反序列化: 用 ObjectInputStream 类读取基本类型数据
注意: ObjectOutputStream 和 ObjectInputStream 不能序列化 static 和 transient 修饰的成员变量
transient 的含义: 不让序列化这个属性
理解
对象序列化机制允许把内存中的 Java 对象转换成平台无关的二进制流, 从而允许把这种二进制流持久地保存在磁盘上, 或通过网络将这种二进制流传输到另一个网络节点. 当其它程序获取了这种二进制流, 就可以恢复成原来的 Java 对象
使用
一个可序列化的 java 对象需要满足的要求
如果需要让某个对象支持序列化机制, 该类必须实现如下两个接口之一, 否则, 会抛出 NotSerializableException 异常
- Serializable(常用)
- Externalizable
需要当前类提供一个全局常量 serialVersionUID
public static final long serialVersionUID = 4892322646L;
其中数值没有严格要求, 随便写一个即可
内部所有属性也必须是可序列化的 (默认情况下, 基本数据类型和 String 是可序列化的)
过程
序列化
创建一个 ObjectOutputStream
调用 ObjectOutputStream 对象的 writeObject( 对象) 方法输出可序列化对象
注意写出一次, 操作 flush() 方法
反序列化
创建一个 ObjectInputStream
调用 readObject() 方法读取流中的对象
注意
如果某个类的属性不是基本数据类型或 String 类型, 而是另一个引用类型, 那么这个引用类型必须是可序列化的 (实现 Serializable 接口), 否则拥有该类型的 Field 的类不能序列化
字符串序列化反序列化操作
序列化
使用 ObjectOutputStream 来实现
- public void test1(){
- // 序列化过程: 将内存中的 java 对象保存在磁盘中或通过网络传输出去
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
- oos.writeObject(new String("我爱北京天安门"));
- oos.flush();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if(oos != null)
- oos.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
反序列化
使用 ObjectInputStream 来实现
- public void test2(){
- // 反序列化过程: 将磁盘文件中对象还原为内存中的一个 java 对象
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(new FileInputStream("object.dat"));
- Object object = ois.readObject();
- String s = (String) object;
- System.out.println(s);
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- try {
- if(ois != null)
- ois.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
自定义类序列化反序列化操作
自定义类
注意自定义类一定要实现 Serializable 接口和有一个全局变量 serialVersionUID
- public class Person implements Serializable {
- public static final long serialVersionUID = 4892322646L;
- 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;
- }
序列化
- public void test1(){
- // 序列化过程: 将内存中的 java 对象保存在磁盘中或通过网络传输出去
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
- oos.writeObject(new String("我爱北京天安门"));
- oos.flush();
- oos.writeObject(new Person("殷志源",42));
- oos.flush();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if(oos != null)
- oos.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
反序列化
- public void test2(){
- // 反序列化过程: 将磁盘文件中对象还原为内存中的一个 java 对象
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(new FileInputStream("object.dat"));
- Object object = ois.readObject();
- String s = (String) object;
- Person p = (Person) ois.readObject();
- System.out.println(s);
- System.out.println(p);
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- try {
- if(ois != null)
- ois.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
serialVersionUID 的理解
相当于一个标识
目的是以序列化对象进行版本控制, 有关各版本反序列化时是否兼容
如果对类进行了修改, 但是定义了 serialVersionUID, 反序列化的时候依旧可以识别出其内容
如果类没有显示定义这个静态常量, 它的值是 Java 运行时环境根据类的内部细节自动生成的. 若类的实例变量做了修改, serialVersionUID 可能发生变化. 所以需要显示声明
对象流
来源: http://www.bubuko.com/infodetail-3655177.html