序列化(写对象)与反序列化(读对象)

序列化(写对象)与反序列化(读对象)

1、java.io.ObjectOutputStream extends OutputStream

对象的序列化流,把对象以流的方式写入文件

构造方法

构造方法 作用
ObjectOutStream(OutputStream out) 创建使用指定OutputStream的 ObjectOutputStream对象

参数:

OutputStream out :字节输出流

特有的一个成员方法

方法 作用
void writeObject(Object obj) 将指定的对象写入到ObjectOutputStream

使用步骤

  • 创建ObjectOutputStream对象,构造方法中传递字节输出流对象
  • 使用ObjectOutputStream对象的writeObject方法,将指定对象写入ObjectOutStream
  • close方法释放资源
package cn.zhuobo.day15.aboutObjectOutputStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        Person p1 = new Person("猪八戒", 360);
        writeObject(p1);
    }

    private static void writeObject(Person p) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day15-code/writeObject.txt"));
        oos.writeObject(p);
        oos.close();
    }
}

但是要注意的是:要要序列化或者反序列化的对象应该是实现了一个java.io.Serializable接口的

Serializable接口:是一个标记类,实现该接口的类会获得一个标记,用来标记对象可以序列化或者反序列化。这个接口内部其实什么也没有,就仅仅是标记作用的标记类。没有实现该接口的类的对象要序列化就会抛出 NotSerializableException

public class Person implements Serializable {
    // body
}

2、java.io.ObjectInputStream extends InputStream

对象的反序列化流,把文件保存的对象以流的方式读取出来

构造方法

构造方法 作用
ObjectInputStream(InputStream in) 创建一个从指定的 InputStream对象中读取的ObjectInputStream

参数

InputStream in : 字节输入流

特有的成员方法

方法 作用
Object readObject() 从ObjectInputStream中读取对象

使用步骤

  • 创建一个ObjectInputStream对象,参数传递字节输入流对象
  • 使用ObjectInputStream对象的readObject方法,读取保存对象的文件
  • 使用close方法释放资源
  • 使用读取的对象
package cn.zhuobo.day15.aboutObjectInputStream;

import cn.zhuobo.day15.aboutObjectOutputStream.Person;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo01ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15-code/writeObject.txt"));

        Object o = ois.readObject();
        ois.close();

       // System.out.println(o.toString());
        Person p = (Person)o;
        System.out.println(p);
    }
}

要注意的是

反序列化的前期:类必须实现了Serializable接口,其次是存在类对应的class文件

readObject方法已经声明了抛出ClassNotFoundException,因此这个异常也要处理,或者继续声明throws或者try catch

反序列化的时候出现 java.io.InvalidClassException,是因为每次对象的类每次生成一个class字节码文件的时候都会计算生成一个UID,如果在序列化只有修改了类,那么该类就会生成新的UID,这就会导致与原来的UID不一致,使得序列化失败。解决方法是人为的定义该类的UID为某一个数字,在类的成员变量中加入以下的声明,这就保证类无论类怎么修改,生成的class文件的UID都是一样的。

private static final long serialVersionUID = 23L;

集合的序列化与反序列化

众所周知,集合也是一个对象,是装了对象的对象,因此将集合序列化也是一样的做法:

package cn.zhuobo.day15.aboutInputStreamReader;

import cn.zhuobo.day15.aboutObjectOutputStream.Person;

import java.io.*;
import java.util.ArrayList;
//将集合的对象序列化,存到文件中
public class Demo02Pratise {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ArrayList<Person> personList = new ArrayList<>();
        personList.add(new Person("猪八戒", 360));
        personList.add(new Person("孙悟空", 550));
        personList.add(new Person("紫霞仙子", 350));
        personList.add(new Person("太上老君", 1150));

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day15-code/writeObject.txt"));
        oos.writeObject(personList);// 序列化

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15-code/writeObject.txt"));
        Object o = ois.readObject();// 反序列化

        ArrayList<Person> list = (ArrayList<Person>)o;// 强制类型转为ArrayList集合
        for (Person person : list) {
            System.out.println(person);
        }

        ois.close();
        oos.close();

    }
}
原文地址:https://www.cnblogs.com/zhuobo/p/10661232.html