一文读懂 Java 序列化与反序列化

序列化与反序列化

Java 将创建出来的对象,存放在 JVM 的对内存中,只有在 JVM 运行的时候,这些对象才会存在,一旦 JVM 停止运行,这些对象的状态也就随之消失了。

但是在一些应用场景中,我们需要将这些对象进行持久化,并且需要在使用的时候能够重新读取对象信息,比如说在 RPC 调用的时候,需要将对象通过网络进行传输,此时就需要下将对象记性序列化进行传输,再将其反序列化进行处理。

序列化(Serialization)是指将对象的状态信息,转换成可以可以存储或传输的形式。在网络传输过程中,可以是字节或是XML等格式。

序列化:Java对象转换为字节序列。
反序列化:字节序列恢复为原先的Java对象。
Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。

Java提供了下面这些类来进行序列化和反序列化

Copy
java.io.Serializable
java.io.Externalizable
ObjectOutput
ObjectInput
ObjectOutputStream
ObjectInputStream
Serializable 接口
java.io.Serializable 是一个没有任何方法或者字段的接口类,仅用于标识这个类可以被序列化。如果要序列化的类有父类,要想同时将在父类中定义过的变量持久化下来,那么父类也应该集成 java.io.Serializable 接口。

Java在进行序列化之前,会检查类是否实现了Serializable接口,没有实现就会报Serializable 接口就会报 NotSerializableException 异常。

往序列化的方法底层看到 java.io.ObjectOutputStream#writeObject0 接口,它对被序列化对象的类型进行了判断,不是字符串、数组、枚举,也没有实现 Serializable 的接口都会抛出 NotSerializableException 异常。

Externalizable 接口
Externalizable继承了Serializable,该接口中定义了两个抽象方法:writeExternal()与readExternal()。当使用Externalizable接口来进行序列化与反序列化的时候需要开发人员重写writeExternal()与readExternal()方法。

serialVersionUID 的作用
反序列化的时候可能遇到 InvalidClassException 异常,说是序列化的时候字节码文件的 serialVersionUID 和本地类的 serialVersionUID 不一致。这是由于反序列化的时候对类进行了修改,比如加上一个 toString 方法打印对象信息。

使用 ObjectOutputStream、ObjectInputStream 进行序列化

Copy
public void serialize() {
User user = new User(“深页”, 18, “杭州”);
try (
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“user.txt”));
) {
oos.writeObject(user);
System.out.println(“Serialized data is saved”);
} catch (IOException e) {
e.printStackTrace();
}
}

public void deserialize() {
try (
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“user.txt”));
) {
User user = (User) ois.readObject();
System.out.println(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
static、transient 修饰不想被序列化的变量
被 static 和 transient 修饰的字段是不会被序列化的:

序列化保存的是对象的状态而非类的状态,所以会忽略 static 静态域;
序列化某个类的对象时,不希望某个字段被序列化,可以用 transient 修饰变量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值