美文网首页
Serializable接口

Serializable接口

作者: 12313凯皇 | 来源:发表于2019-05-01 14:01 被阅读0次

一、概述

SerializableJava所提供的一个序列化接口,它是一个空接口为对象提供标准的序列化和反序列化操作。使用Serializable来实现序列化相当简单,只需要在类的声明中指定一个类似下面的标识即可自动实现默认的序列化过程。

private static final long serialVersionUID = -499137596716953701L;

Android中还提供了新的序列化方法:Parcelable接口,关于Parcelable可以跳转到我的另一篇文章:。本文仅对Serializable接口进行介绍。

实际上,想要一个对象可以实现序列化,只需要让这个类实现Serializable接口即可,甚至连上面的serialVersionUID都不是必需的,如果不声明serialVersionUID同样也可以实现序列化,但是将会对反序列化过程产生影响,原因在后面解释。下面先来看一个Demo示例。

二、示例

首先定义一个User类:

public class User implements Serializable {


    private static final long serialVersionUID = -499137596716953701L;

    public int userId;

    public String userName;

    public boolean isMale;

    public User(int userId, String userName, boolean isMale) {
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", isMale=" + isMale +
                '}';
    }
}

通过Serializable方式实现对象的序列化,实现起来非常简单,几乎所有工作都被系统自动完成了。我们只需要通过ObjectOutputStreamObjectInputStream即可轻松实现,代码如下所示:

//序列化过程
User user = new User(0, "jake", true);
try {
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
    out.writeObject(user);
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}


//反序列化过程
try {
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
    User newUser = (User) in.readObject();
    System.out.println(newUser);
    in.close();
} catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
}

输出结果:

User{userId=0, userName='jake', isMale=true}

三、serialVersionUID

下面来讲一下serialVersionUIDserialVersionUID用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同才能够正常地的被反序列化。serialVersionUID的详细工作机制是这样的:序列化的时候系统会去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化;否则就说明当前类和序列化的类相比发生了某些变换,这时是无法正常反序列化的,因此会报如下错误:

java.io.InvalidClassException: serializable.User; local class incompatible: stream classdesc serialVersionUID = -499137596716953701, local class serialVersionUID = -499137596716953702

一般来说,我们应该手动指定serialVersionUID的值,比如1L,也可以通过编译器自动生成,笔者使用的是IDEA,默认情况下是不会提示生成serialVersionUID的,需要在settings中设置,如下图所示:


设置完成后,没有设置实现了serializable接口的类如果没有设置serialVersionUID将会报警告。

不管是手动设置还是通过工具去生成,本质上没有区别,需要注意的是,静态成员变量属于类不属于对象,所以不参与序列化过程。其次用transient关键字标记的成员变量不参与序列化过程

另外,系统默认序列化过程也是可以改变的,通过实现如下两个方法即可重写系统默认的序列化和反序列化过程,不过大部分情况下我们不需要重写这两个方法。

private void readObject(ObjectInputStream in) throws IOException {

}

private void writeObject(ObjectOutputStream outputStream) throws IOException, ClassNotFoundException {

}

相关文章

网友评论

      本文标题:Serializable接口

      本文链接:https://www.haomeiwen.com/subject/tcvinqtx.html