目录
一、引言
二、用户登录存档:让账号信息「冻龄」不变
1. 给对象贴「冷冻标签」:实现 Serializable
2. 冷冻与解冻实战:把用户存进文件
3. 演示场景
三、游戏存档复活:让角色进度「穿越时空」
1. 复杂对象冷冻:游戏角色的「时空胶囊」
2. 存档管理器:战斗前先「存个档」
3. 实战剧情
四、serialVersionUID:防止「冷冻变质」的关键
1. 版本号为什么重要?
2. 版本号升级场景
五、序列化避坑指南:这些「冰锥」要小心!
1. 静态字段不冷冻:
六、总结
一、引言
欢迎来到 Java「对象冷冻厂」!今天我们要解锁一项程序员必备技能 ——序列化与反序列化,俗称「对象冷冻术」。简单来说,就是把 Java 对象变成能存进文件、传上网线的「数据冰块」,需要时再「解冻」复活。无论是保存用户登录状态,还是让游戏角色进度「起死回生」,这套技能都能让你轻松实现「对象持久化自由」。
二、用户登录存档:让账号信息「冻龄」不变
1. 给对象贴「冷冻标签」:实现 Serializable
// 用户类:贴上「可冷冻」标签
public class User implements Serializable {// 冷冻身份证:版本号必须手动填写!private static final long serialVersionUID = 123456789L; private String username;private transient String password; // 敏感字段不冷冻private int age;// ... 省略构造方法和Getter/Setter
}
关键点:Serializable
接口就像对象的「冷冻许可证」,而serialVersionUID
是每个对象冷冻后的「唯一条形码」,修改类结构时必须小心维护,否则会导致「解冻失败」!
2. 冷冻与解冻实战:把用户存进文件
// 冷冻机:将对象写入文件
public static void freezeUser(User user, String path) {try (ObjectOutputStream freezer = new ObjectOutputStream(new FileOutputStream(path))) {freezer.writeObject(user); // 把对象「冻」进文件System.out.println("用户已冷冻保存!");} catch (IOException e) {e.printStackTrace();}
}// 解冻机:从文件恢复对象
public static User thawUser(String path) {try (ObjectInputStream thawer = new ObjectInputStream(new FileInputStream(path))) {return (User) thawer.readObject(); // 把「冰块」变回对象} catch (Exception e) {System.out.println("解冻失败:" + e.getMessage());return null;}
}
3. 演示场景
public static void main(String[] args) {User bob = new User("Bob", "secret", 25);freezeUser(bob, "user.dat"); // 保存登录状态// 模拟重启后解冻User recovered = thawUser("user.dat");System.out.println("解冻成功:" + recovered); // 输出完整用户信息(除了transient的password)
}
三、游戏存档复活:让角色进度「穿越时空」
1. 复杂对象冷冻:游戏角色的「时空胶囊」
// 游戏角色类:包含装备列表的复杂对象
public class GameRole implements Serializable {private static final long serialVersionUID = 987654321L;private String name;private int level;private List<String> equipments; // 装备列表自动支持冷冻// 带装备的构造方法public GameRole(String name, int level, List<String> equipments) {this.name = name;this.level = level;this.equipments = equipments;}
}
注意:只要对象的属性都是可序列化的(如List
、String
),复杂对象也能一键冷冻!
2. 存档管理器:战斗前先「存个档」
// 存档方法:把角色冻进存档文件
public static void saveGame(GameRole role, String slot) {try (ObjectOutputStream saveFile = new ObjectOutputStream(new FileOutputStream("save_" + slot + ".dat"))) {saveFile.writeObject(role);System.out.println("已在" + slot + "号存档点保存进度!");} catch (IOException e) {System.out.println("存档失败:" + e.getMessage());}
}// 读档方法:从存档恢复角色
public static GameRole loadGame(String slot) {try (ObjectInputStream loadFile = new ObjectInputStream(new FileInputStream("save_" + slot + ".dat"))) {return (GameRole) loadFile.readObject();} catch (Exception e) {System.out.println("读档失败:" + e.getMessage());return null;}
}
3. 实战剧情
public static void main(String[] args) {// 新建角色:1级小菜鸟,只有木剑List<String> starterEq = Arrays.asList("木剑", "布甲");GameRole hero = new GameRole("勇者林克", 1, starterEq);saveGame(hero, "slot1"); // 存档// 模拟打怪升级(修改对象状态)hero.setLevel(100);hero.getEquipments().add("大师之剑");// 读档!回到1级状态GameRole reloaded = loadGame("slot1");System.out.println("读档角色:" + reloaded); // 输出1级+木剑布甲,修改后的状态未保存
}
四、serialVersionUID:防止「冷冻变质」的关键
1. 版本号为什么重要?
想象你把对象冻成冰块后,修改了类的结构(比如删了个字段),再解冻时 Java 会报错:「冰块条形码和当前类不匹配!」
手动指定版本号:
private static final long serialVersionUID = 1L; // 写死版本号,修改类时谨慎更新
2. 版本号升级场景
- 兼容修改(如新增可选字段):保持版本号不变,反序列化时自动填充默认值。
- 不兼容修改(如删除核心字段):必须更新版本号,并编写数据迁移逻辑。
五、序列化避坑指南:这些「冰锥」要小心!
1. 静态字段不冷冻:
private static String serverName = "主服"; // 静态字段属于类,不会存入对象冰块
2. transient 关键字:排除敏感字段:
private transient String creditCardNumber; // 银行卡号不参与冷冻
3. 深度克隆技巧:通过序列化实现对象深拷贝,比手动复制属性更省心:
public static <T> T deepClone(T object) {try (ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais)) {oos.writeObject(object);return (T) ois.readObject();} catch (Exception e) {throw new RuntimeException("克隆失败", e);}
}
六、总结
Java 序列化与反序列化是通过实现Serializable
接口将对象转为数据流实现持久化存储的技术,可用于用户登录信息保存、游戏存档恢复等场景,需手动维护serialVersionUID
控制兼容性,利用transient
排除敏感字段,注意静态字段不参与序列化。