io 14.0 使用对象流实现序列化

使用对象流实现序列化

如果需要将某个对象保存到磁盘上或者通过网络传输,那么这个类应该实现 Serializable 接口或者 Externalizable 接口之一。

使用 Serializable 来实现序列化非常简单,主要让目标类实现 Serializable 标记接口即可,无须实现任何方法。
一旦某个类实现了 Serializable 接口,该类的对象就是可序列化的,程序可以通过如下两个步骤来序列化该对象。

序列化

  1. 创建一个ObjectOutputStream,这个输出流是一个处理流,所以必须建立在其他节点流的基础之上。
  2. 调用ObjectOutputStream对象的writeObject()方法输出可序列化对象。

定义一个普通的Java类,只是实现了Serializable接口,该接口标识该类的对象是可序列化的。

public class Canine implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    public Canine(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class ObjectStreamTest {
    public static void main(String[] args) {
        try(
                FileOutputStream outputStream = new FileOutputStream("src\\com\\rrz\\object.txt");
                ObjectOutputStream oOut = new ObjectOutputStream(outputStream);
        ) {
            oOut.writeObject(new Canine("狮子"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

运行上面程序,将会生成一个 object.txt 文件
在这里插入图片描述
打开是乱码的,因为编码解码不一致导致

反序列化

从二进制流中恢复 java 对象

  1. 创建一个ObjectInputStream输入流,这个输入流是一个处理流,所以必须建立在其他节点流的基础之上。
  2. 调用ObjectInputStream对象的readObject()方法读取流中的对象,该方法返回一个Object类型的Java对象,如果程序知道该Java对象的类型,则可以将该对象强制类型转换成其真实的类型。

主要看构造器

public class Canine implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    public Canine(String name) {
        System.out.println("这是一个有参数的构造器");
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

反序列化

public class ObjectStreamTest {
    public static void main(String[] args) {
        try(
                FileInputStream inputStream = new FileInputStream("src\\com\\rrz\\object.txt");
                ObjectInputStream in = new ObjectInputStream(inputStream);
        ) {
            Canine object = (Canine) in.readObject();
            System.out.println(object.getName());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

结果

在这里插入图片描述

看到并没有打印“这是一个有参数的构造器”,说明并没有调用构造器

必须指出的是,反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供该Java对象所属类的class文件,否则将会引发ClassNotFoundException异常。

还有一点需要指出:Canine 类只有一个有参数的构造器,没有无参数的构造器,而且该构造器内有一个普通的打印语句。当反序列化读取Java对象时,并没有看到程序调用该构造器,这表明反序列化机制无须通过构造器来初始化Java对象。

提示:
在ObjectInputStream输入流中的readObject()方法声明抛出了ClassNotFoundException异常,也就是说,当反序列化时找不到对应的Java类时将会引发该异常。

如果使用序列化机制向文件中写入了多个Java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。

当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参数的构造器,要么也是可序列化的——否则反序列化时将抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类中定义的成员变量值不会序列化 到二进制流中。

上一节:序列化的含义和意义
下一节:对象引用的序列化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值