《网络安全学习者必看!Java序列化与反序列化深度解读》

序列化与反序列化的代码讲解

基本实现

这里我们可以先跑一跑代码,看一看。

Run SerializationTest.java

Run UnserializationTest.java

前文我们说,序列化与反序列化的根本目的是数据的传输。

  • SerializationTest.java

咱们来想象一个有趣的小实验:把Java对象变成魔法饼干存进罐子里!

你心爱的玩具需要保存起来,方便下次继续玩

  1. 【准备魔法罐子】首先咱们要找一个透明的密封罐(FileOutputStream),用来装我们的魔法饼干
    FileOutputStream就像个透明玻璃罐,用来存放最终的成果:"ser.bin"就是我们的魔法饼干罐
  2. 【施展序列化魔法】然后拿出神奇裱花袋(ObjectOutputStream),把裱花嘴套在罐口上
    ObjectOutputStream就像能把对象变成数据流的神奇工具,接在罐子上准备输出
  3. 【注入对象精华】最后像挤奶油一样,把Java对象"滋溜"一下挤进罐子!
    oos.writeObject(obj) 这一瞬间,你的对象就被转化成魔法数据,永久保存在二进制文件里啦~

下次想找回玩具时,用ObjectInputStream这个反向魔法,就能把饼干变回原来的玩具对象啦!就像这样:

java 复制代码
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));  
Object recoveredToy = ois.readObject();

Serializable 接口

(1) 序列化类的属性没有实现 Serializable 那么在序列化就会报错

想象你要参加「对象王国」的狂欢派对,入场券就是这个Serializable接口!🎫

▶️ 特点:

  1. 空白的魔法契约

    public class MagicCookie implements Serializable { ... }

    • 只需在类头顶上贴上这个标签(implements Serializable
    • 不用写任何魔法咒语(不需要实现任何方法)
    • 就像拿到一张「免笔试入场券」
  2. 自动触发魔法阵

    java 复制代码
    oos.writeObject(cookie); // ✨ 自动施放序列化咒语
    • Java会悄悄检查你的「入场券」
    • 如果没贴标签?→ 抛出InvalidClassException(就像被保安拦在派对门外!)
java 复制代码
public class Person implements Serializable { // 🎯 正确佩戴许可证!
    private String name;
    private int age;
}

当删除implements Serializable时:

java 复制代码
public class Person { // 😱 许可证被偷了!
    private String name;
    private int age;
}

👉 ​后果:运行时会弹出超恐怖的红色警告!

Exception in thread "main" java.io.NotSerializableException: src.Person

就像你试图带着普通书包穿越时空隧道,被守卫机器人用激光枪拦截!

终极比喻记忆法 🧩

  • Serializable → 免费基础会员卡(躺平就能用)
  • Externalizable → VIP定制服务(需要自己动手配置)
  • 未实现接口 → 想带宠物进电影院却没买宠物票(一定会被拦下!)
  • JVM → 严格的时空管理局警察(检查你的证件!)

此外,如果我们此处将 Serializable 接口删除掉的话,会导致如下结果。

(2) 在反序列化过程中,它的父类如果没有实现序列化接口,那么将需要提供无参构造函数来重新创建对象。
(3)一个实现 Serializable 接口的子类也是可以被序列化的。
(4) 静态成员变量是不能被序列化

序列化是针对对象属性的,而静态成员变量是属于类的。

(5) transient 标识的对象成员变量不参与序列化")(5) transient 标识的对象成员变量不参与序列化

这里我们可以动手实操一下,想这么一个问题

  • 如何让Java对象的敏感信息"瞬间消失"?

🎯 ​任务背景

你是一名Java特工,需要护送Person对象穿越「序列化隧道」到另一个系统。但有个致命问题

⚠️ ​**name是绝密信息,绝对不能泄露!​**

怎么办?快用transient隐身喷雾!

🕶️ ​STEP 1:装备隐身喷雾(修改Person类)​

打开Person.java,找到第7行秘密武器库:

java 复制代码
// 原版(危险!名字会被记录)
private String name;

// 特工改造版 → 喷上transient隐身喷雾!
private transient String name;  // 🕶️ 隐身模式启动

💻 ​STEP 2:执行加密传输(序列化测试)​

运行SerializationTest.java,观察特工日志:

java 复制代码
// 序列化前的对象状态
Person{name='aa', age=22} 

// 穿越序列化隧道后...
System.out.println("序列化文件内容:");
// 用hex编辑器查看ser.bin → name字段已消失!🚀

🔓 ​STEP 3:接收端解密验证(反序列化测试)​

运行UnserializeTest.java,发现惊人变化:

java 复制代码
// 反序列化后的对象
Person{name='null', age=22} 
// ❗ name变成null,但age完好无损!

🚀 ​完整特工代码(SerializationTest.java

java 复制代码
package com.tingjun;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializationTest {

    public static void serialize(Object obj) throws IOException {
        // 🕶️ 创建序列化隧道入口
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
        oos.close(); // 重要!关闭资源
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 🎯 特工代号设置
        Person person = new Person("aa", 22);
        System.out.println("【特工出发前状态】");
        System.out.println(person); // Person{name='aa', age=22}

        // 🚀 启动序列化传送
        serialize(person);

        // 🔍 接收端反序列化检测
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
        Person deserializedPerson = (Person) ois.readObject();
        ois.close();

        System.out.println("\n【穿越序列化隧道后】");
        System.out.println("序列化文件内容:"); // ✨ 关键输出位置!
        System.out.println(deserializedPerson); // Person{name='null', age=22}
    }
}

上述说的还是关于序列化本身的一些特性,明天我们接着讲一讲序列化的安全问题是如何产生的。

相关推荐
aimmon几秒前
Rust从入门到精通之精通篇:25.过程宏高级应用
开发语言·后端·rust
多多*1 分钟前
使用事件监听器来处理并发环境中RabbitMQ的同步响应问题
java·开发语言·spring boot·分布式·docker·mybatis
农夫阿才4 分钟前
排序算法总结
java·算法·排序算法
金融数据出海8 分钟前
使用Java对接印度股票数据源
后端
神马行空9 分钟前
一文解读DeepSeek的安全风险、挑战与应对策略
网络·人工智能·安全·大模型·deepseek
uhakadotcom13 分钟前
Kubernetes Ingress NGINX Controller 详解
后端·面试·github
uhakadotcom16 分钟前
代码混淆:保护软件安全的利器
后端·面试·github
aiopencode17 分钟前
android crash_log 文件分析
后端
失业写写八股文19 分钟前
如何选择栈与堆?堆跟栈的区别
java·后端