Java 序列化与反序列化

一、 序列化(Serialization)

     将 Java 对象转换为‌字节流‌的过程,使其能够被存储(如保存到文件、数据库)或传输(如网络通信)。

作用:持久化对象状态、跨平台传输、支持分布式计算(如 RPC)

技术要求‌:

  • 类需实现 java.io.Serializable 标记接口(无方法,仅标识可序列化)。
  • 使用 ObjectOutputStream.writeObject() 将对象写入字节流。
  • 可通过 transient 关键字排除敏感或临时字段。

二、反序列化(Deserialization)

将‌字节流‌恢复为内存中的 Java 对象的过程。

作用:重建对象状态、接收远程数据、恢复持久化数据

技术要求‌:

  •  使用 ObjectInputStream.readObject() 从字节流读取对象。
  •  反序列化的类需与序列化时的类结构兼容(否则抛出 InvalidClassException)。
  •   显式定义 serialVersionUID 控制版本一致性,避免类定义变更导致兼容性问题。

三、两者关系

维度序列化反序列化
目的对象 → 字节流(存储/传输)字节流 → 对象(恢复/使用)
接口依赖类必须实现 Serializable同序列化要求,且需保证类定义兼容性
核心方法ObjectOutputStream.writeObject()ObjectInputStream.readObject()
数据控制transient 字段不参与序列化依赖序列化时的字段值重建对象
安全风险暴露敏感字段(若未用 transient不可信数据可能导致代码执行漏洞(需验证来源或使用白名单)
典型应用保存对象到文件、发送网络请求、缓存数据读取文件恢复对象、接收网络数据、反序列化缓存

注意事项

  1. 兼容性‌:若序列化后修改类结构(如增删字段),需保持 serialVersionUID 一致,否则反序列化失败。
  2. 性能‌:Java 原生序列化可能效率较低,跨语言场景建议使用 JSON/XML 或高效二进制协议。
  3. 安全性‌:避免反序列化不可信数据,防止攻击者构造恶意字节流触发漏洞。

通过序列化与反序列化,Java 实现了对象状态的持久化和跨环境交互,是分布式系统、缓存机制等场景的底层基础技术。

 

四、数据持久化应用 

1、封装序列化和反序列化方法(使用泛型

package org.ser;

import java.io.*;

public class InitSerialize {
    /**
     * 序列化对象
     *
     * @param obj  对象
     * @param path 路径
     */
    public <T> void serializeObject(T obj, String path) {
        // 序列化对象到文件
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));) {
            // 写入对象到文件
            oos.writeObject(obj);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 反序列化对象
     *
     * @param path 路径
     * @param <T>  泛型类型
     * @return
     */
    public <T> T deserializeObject(String path) {
        // 反序列化对象
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
            // 读取对象
            return (T) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

}

2、用户类实现序列化接口

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
//    private transient int age; // 不会被序列化
    private  int age; //

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

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

3、测试类

package org.ser;

import java.util.Arrays;
import java.util.List;

public class TestSer {
    public static void main(String[] args) {
        //实例化对象
        InitSerialize initSerialize = new InitSerialize();

        //单个对象的操作
        one(initSerialize);

        //多个对象的操作
//        more(initSerialize);


    }

    private static void one(InitSerialize initSerialize) {
        //用户对象
        User user = new User("Sergey", 25);
        //序列化对象到文件
        initSerialize.serializeObject(user, "user.ser");
        //反序列化对象从文件
        User user1 = initSerialize.deserializeObject("user.ser");
        System.out.println(user1);
    }

    private static void more(InitSerialize initSerialize) {
        //多个对象的操作
        User user2 = new User("mike", 20);
        User user3 = new User("boy", 18);
        User user4 = new User("girl", 19);
        User user5 = new User("little", 17);
        //对象数组
        User[] users = new User[]{user2, user3, user4, user5};
        //序列化对象数组到文件
        initSerialize.serializeObject(users, "users.ser");
        //反序列化对象数组从文件
        User[] users1 = initSerialize.deserializeObject("users.ser");
        //将数组转换为列表
        List<User>  list = Arrays.asList(users1);
        //Lambda表达式遍历并打印用户信息
        list.forEach(System.out::println);
    }
}

4、运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值