Java 对象序列化


几乎只要是 Java 开发就一定会存在有序列化的概念,而正是因为序列化的概念逐步发展,慢慢地也有了更多 的序列化标准

什么是序列化?

所谓的对象序列化指的是将内存中保存的对象以二进制数据流的形式进行处理,可以实现对象的保存或者是网络传输
在这里插入图片描述
然而并不是所有的对象都可以被序列化的,在 Java 里面有一个强制性的要求:如果要序列化的对象,那么对象所在的类一定要实现 java.io.Serializable 父接口,作为序列化的标记,这个接口并没有任何的方法,为什么?因为它描述的是一种类的能力

举例:(定义一个可以被序列化的类)

class Person implements Serializable { // Person 类可以被序列化
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略 setter getter

    @Override
    public String toString() {
        return "姓名:" + this.name + "、年龄:" + this.age;
    }
}

此时 Person 类产生的每一个对象都可以实现二进制的数据传输,属于可以被序列化的程序类

序列化与反序列化

有了序列化的支持类之后如果想要实现序列化与反序列化的操作则就可以利用以下两个类完成:

类名称序列化:ObjecOutputStream反序列化:ObjectInputStream
类定义public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstantspublic class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
构造方法public ObjectOutputStream(OutputStream out) throws IOExceptionpublic ObjectInputStream(InputStream in) throws IOException
操作方法public final void writeObject(Object obj) throws IOExceptionpublic final Object readObject() throws IOException, ClassNotFoundException

举例:(实现序列化与反序列化)

package com.java.springtest.testdemo;

import java.io.*;

/**
 * @author Woo_home
 * @create by 2020/1/31
 */

class Person implements Serializable { // Person 类可以被序列化
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略 setter getter

    @Override
    public String toString() {
        return "姓名:" + this.name + " 年龄:" + this.age;
    }
}

public class Demo {

    private static final File SAVE_FILE = new File("D:" + File.separator + "demo.person");

    public static void saveObject(Object object) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
        oos.writeObject(object); // 序列化
        oos.close();
    }

    public static Object loadObject() throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
        Object obj = ois.readObject(); // 反序列化
        ois.close();
        return obj;
    }

    public static void main(String[] args) throws Exception {
        saveObject(new Person("lisa",10));// 序列化
        System.out.println(loadObject()); // 反序列化
    }
}

运行该程序之后会在 D 盘生成一个 demo.person 的文件
在这里插入图片描述
我们打开这个文件发现它存储的是一个二进制
在这里插入图片描述
控制台输出:
在这里插入图片描述
在 Java 中的对象序列化与反序列化必须使用内部提供的对象操作流,因为这里面牵扯到二进制数据的格式,所以不能自定义处理,另外如果想要实现一组对象的序列化,则可以使用对象数组完成

在很多的实际项目开发过程之中,开发者很少能够见到 ObjectOutputStream、ObjectInputStream 类的直接操作,因为会有一些容器帮助开发者自动实现

transient 关键字

默认情况下当执行了对象序列化的时候会将类中的全部属性的内容进行全部的序列化操作,但是很多情况下有一些属性可能并不需要进行序列化的处理,这个时候就可以在属性定义上使用 transient 关键字来完成了

private transient String name;

如果在属性加上了 transient 关键字之后,那么在进行序列化处理的时候 name 属性的内容是不会被保存下来的,换言之,读取的数据 name 将是其对应数据类型的默认值(null)

举例:(transient 关键字的使用)

我们把上门的程序中的 name 属性加上 transient 关键字之后再执行一次,可以看到 name 输出为 null 了
在这里插入图片描述

什么时候会使用到 transient 关键字?

如果假设类之中有一些是需要计算保存的属性内容往往是不需要被序列化的,这个时候就可以使用 transient 关键字了,但是呢在实际上的开发之中大部分需要被序列化的类往往都是简单的 Java 类(比如 Java web 开发中的实体类),所以这一个关键字的出现频率并不高,但是得知道有这么一个关键字叫 transient

  • 16
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值