博客
关于我
day19Java-其它IO-ObjectIn(Out)putStream-(反)序列化流
阅读量:268 次
发布时间:2019-03-01

本文共 4018 字,大约阅读时间需要 13 分钟。

ObjectInputStream与ObjectOutputStream - 序列化与反序列化流

在Java编程中,ObjectInputStream和ObjectOutputStream是处理对象序列化和反序列化的核心类。ObjectOutputStream用于将对象转化为流数据,以便在文本文件中存储或通过网络传输。而ObjectInputStream则用于将流数据还原为对象。这两者在数据传输和持久化存储中发挥着重要作用。

ObjectOutputStream - 序列化流

使用ObjectOutputStream进行对象序列化时,首先需要确保目标类实现了Serializable接口。该接口是一个标记接口,类通过实现它可以启用其序列化功能。如果未实现该接口的类将无法进行序列化或反序列化操作,会抛出NotSerializableException异常。

实现Serializable接口的重要性

以下是实现Serializable接口的示例代码:

public class Person implements Serializable {    private String name;    private int age;    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;    }}

如果类Person未实现Serializable接口,尝试将其序列化就会抛出以下错误信息:

Exception in thread "main" java.io.NotSerializableException: com.ginger.demo01.Person    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)    at com.ginger.demo01.ObjectInputStreamDemo.writer(ObjectInputStreamDemo.java:24)    at com.ginger.demo01.ObjectInputStreamDemo.main(ObjectInputStreamDemo.java:8)

ObjectInputStream - 反序列化流

在反序列化过程中,如果类没有指定序列化版本号(serialVersionUID),可能会出现InvalidClassException。以下是一个常见的解决方案:

  • 在类中手动指定序列化版本号:
  • public class Person implements Serializable {    private static final long serialVersionUID = 6499259360078010285L;    private String name;    private int age;    // 其他代码保持不变}
    1. 如果需要修改类结构后仍能读取已存在的序列化文件,可以通过在类中使用transient关键字来控制哪些字段参与序列化:
    2. public class Person implements Serializable {    private static final long serialVersionUID = 6499259360078010285L;    private String name;    private transient String chinese; // 使用transient关键字使chinese字段不参与序列化    // 其他代码保持不变}

      代码示例

      以下是一个完整的代码示例,展示了如何使用ObjectInputStream和ObjectOutputStream进行数据的读写操作:

      写入流数据

      public class ObjectInputStreamDemo {    public static void main(String[] args) throws IOException, ClassNotFoundException {        writer();    }    private static void writer() throws IOException {        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));        Person p = new Person("格雷福斯", 40);        oos.writeObject(p);        oos.close();    }}

      读取流数据

      public class ObjectInputStreamDemo {    public static void main(String[] args) throws IOException, ClassNotFoundException {        reader();    }    private static void reader() throws IOException, ClassNotFoundException {        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));        Object p = ois.readObject();        System.out.println(p);        ois.close();    }}

      实体类定义

      以下是一个实现了Serializable接口的实体类:

      public class Person implements Serializable {    private static final long serialVersionUID = 6499259360078010285L;    private String name;    private int age;    private transient String chinese;    public Person(String name, int age, String chinese) {        this.name = name;        this.age = age;        this.chinese = chinese;    }    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;    }    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                ", chinese='" + chinese + '\'' +                '}';    }}

      结果分析

      在实际应用中,如果没有指定serialVersionUID,可能会出现以下错误:

      InvalidClassException: com.ginger.demo01.Person; local class incompatible:     stream classdesc serialVersionUID = 311183030272692197,    local class serialVersionUID = 6499259360078010285

      解决方法

    3. 确保所有修改后的类都包含相同的serialVersionUID值。
    4. 如果需要在修改类后仍能读取已存在的序列化文件,可以通过在类中使用transient关键字来控制哪些字段参与序列化。
    5. 结论

      通过以上方法,开发者可以实现对象的序列化和反序列化操作。在实际开发中,建议在类定义时手动指定serialVersionUID,并合理使用transient关键字,以确保序列化过程的稳定性和兼容性。

    转载地址:http://hlya.baihongyu.com/

    你可能感兴趣的文章
    Nuget~管理自己的包包
    查看>>
    NuGet学习笔记001---了解使用NuGet给net快速获取引用
    查看>>
    nullnullHuge Pages
    查看>>
    NullPointerException Cannot invoke setSkipOutputConversion(boolean) because functionToInvoke is null
    查看>>
    null可以转换成任意非基本类型(int/short/long/float/boolean/byte/double/char以外)
    查看>>
    Numix Core 开源项目教程
    查看>>
    numpy
    查看>>
    NumPy 库详细介绍-ChatGPT4o作答
    查看>>
    NumPy 或 Pandas:将数组类型保持为整数,同时具有 NaN 值
    查看>>
    numpy 或 scipy 有哪些可能的计算可以返回 NaN?
    查看>>
    numpy 数组 dtype 在 Windows 10 64 位机器中默认为 int32
    查看>>
    numpy 数组与矩阵的乘法理解
    查看>>
    NumPy 数组拼接方法-ChatGPT4o作答
    查看>>
    numpy 用法
    查看>>
    Numpy 科学计算库详解
    查看>>
    Numpy.fft.fft和numpy.fft.fftfreq有什么不同
    查看>>
    Numpy.ndarray对象不可调用
    查看>>
    Numpy:按多个条件过滤行?
    查看>>
    Numpy:条件总和
    查看>>
    numpy、cv2等操作图片基本操作
    查看>>