Skip to content

什么是序列化和反序列化?

  • 序列化(Serialization): 将java对象转换成字节流的过程。以便可以将这些字节流保存到文件、数据库中或通过网络传输。主要作用是实现对象的持久化存储和传输。
  • 反序列化(Deserialization): 将字节流恢复为java对象的过程。

实现方式

1.实现 Serializable 接口(最常用)

java
import java.io.Serializable;

public class ClassName implements Serializable {
    // 序列化版本ID,可选但推荐添加
    private static final long serialVersionUID = 1L;
    
    // 类成员
    private transient DataType fieldName; // transient 修饰的字段不会被序列化
    
    // 构造方法、getter/setter等
}

2.实现 Externalizable 接口(自定义序列化)

java
import java.io.Externalizable;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class ClassName implements Externalizable {
    // 必须有无参构造方法
    public ClassName() {}
    
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // 自定义序列化逻辑
    }
    
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // 自定义反序列化逻辑
    }
}

重点注意事项

serialVersionUID

serialVersionUID表示序列化版本号,用于标识类的版本。如果累的结构发生变化(新增字段或修改字段类型等),serialVersionUID不匹配会导致反序列化失败。不申明serialVersionUID,jvm编译器会自动生成一个版本号,但容易导致版本不一致,所以建议显式声明 serialVersionUID: private static final long serialVersionUID = 1L;

transient 关键字

标记字段不会被序列化,适用于敏感信息或临时数据。反序列化时,transient字段会被还原成默认值(如int为0,String为null等)。

静态字段

静态字段不会被序列化,因为它们属于类而不是对象。

继承关系中的序列化

父类实现了序列化,子类自动可序列化。

安全性问题

序列化和反序列化存在安全风险,尤其是反序列化时:反序列化恶意数据可能导致代码执行或数据泄露。 解决方案:

  • 1.自定义readObject和writeObject方法:在类中覆盖readObject和writeObject方法,验证数据的合法性。
  • 2.使用安全的序列化框架:避免使用java默认的序列化机制,改用更安全的框架(如protobuf,kryo)
  • 3.敏感数据使用transient修饰,保证不被序列化。

性能优化问题

java默认的序列化机制效率较低,可以通过以下方式优化:

  • 1.使用externalizable接口:它是serializble的子接口,允许自定义序列化逻辑。通过实现writeExternal和readExternal方法,可以减少序列化数据的大小。
  • 2.使用高效的序列化库:如protobuf、kryo、fst等。

Released under the MIT License.