java中的序列化

Posted 四猿外

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中的序列化相关的知识,希望对你有一定的参考价值。

序列化

Java 的序列化就是将一个 Java 对象转化为一个字节流的一种机制。从字节流再转回 Java 对象叫做反序列化,是序列化的反向操作。

序列化和反序列化是和平台无关的,也就是说你可以在 Linux 系统序列化,然后在 Windows 操作系统做反序列化。

如果要序列化对象,需要使用 ObjectOutputStream 类的 writeObject() 方法。如果要做反序列化,则要使用 ObjectOutputStream 类的 readObject() 方法。

如下图所示,对象被转化为字节流后,被储存在了不同的介质中。这个流程就是序列化。在图的右边,也可以看到从不同的介质中,比如内存,获得字节流并转化为对象,这叫做反序列化。
在这里插入图片描述

为什么使用序列化

如果我们创建了一个 Java 对象,这个对象的状态在程序执行完毕或者退出后就消失了,不会得到保存。

所以,为了能解决这类问题,Java 提供了序列化机制。这样,我们就能把对象的状态做临时储存或者进行持久化,以供后续当我们需要这个对象时,可以通过反序列化把对象还原回来。

下面给出一些代码看看我们是怎么来做序列化的。

import java.io.Serializable;

public class Player implements Serializable {

    private static final long serialVersionUID = 1L;

    private String serializeValueName;
    private transient String nonSerializeValuePos;

    public String getSerializeValueName() {
        return serializeValueName;
    }

    public void setSerializeValueName(String serializeValueName) {
        this.serializeValueName = serializeValueName;
    }

    public String getNonSerializeValueSalary() {
        return nonSerializeValuePos;
    }

    public void setNonSerializeValuePos(String nonSerializeValuePos) {
        this.nonSerializeValuePos = nonSerializeValuePos;
    }

    @Override
    public String toString() {
        return "Player [serializeValueName=" + serializeValueName + "]";
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializingObject {
    public static void main(String[] args) {

        Player playerOutput = null;
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        playerOutput = new Player();
        playerOutput.setSerializeValueName("niubi");
        playerOutput.setNonSerializeValuePos("x:1000,y:1000");

        try {
            fos = new FileOutputStream("Player.ser");
            oos = new ObjectOutputStream(fos);
            oos.writeObject(playerOutput);

            System.out.println("序列化数据被存放至Player.ser文件");

            oos.close();
            fos.close();

        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

Output:
序列化数据被存放至Player.ser文件

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

public class DeSerializingObject {

    public static void main(String[] args) {

        Player playerInput = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;

        try {
            fis = new FileInputStream("Player.ser");
            ois = new ObjectInputStream(fis);
            playerInput = (Player) ois.readObject();

            System.out.println("从Player.ser文件中恢复");

            ois.close();
            fis.close();

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("player名字为 : " + playerInput.getSerializeValueName());
        System.out.println("player位置为 : " + playerInput.getNonSerializeValuePos());
    }
}

Output:

从Player.ser文件中恢复
player名字为 : niubi
player位置为 : null

关键特性

  1. 如果父类实现了 Serializable 接口那么子类就不必再实现 Serializable 接口了。但是反过来不行。
  2. 序列化只支持非 static 的成员变量
  3. static 修饰的变量和常量以及被 transient 修饰的变量是不会被序列化的。所以,如果我们不想要序列化某些非 static 的成员变量,直接用 transient 修饰它们就好了。
  4. 当反序列化对象的时候,是不会调用对象的构造函数的。
  5. 如果一个对象被一个要序列化的对象引用了,这个对象也会被序列化,并且这个对象也必须要实现 Serializable 接口。

以上是关于java中的序列化的主要内容,如果未能解决你的问题,请参考以下文章

(转) Java中的负数及基本类型的转型详解

如何在 Java 中播放(MIDI)序列中的音频剪辑?

有没有办法关闭代码片段中的命名建议?

片段 A 的列表视图中的片段 B 中的新列表视图,单击 A 的列表项

ASP.net MVC 代码片段问题中的 Jqgrid 实现

如何从 Firebase 获取数据到 Recyclerview 中的片段?