Java 序列化和Java反射的底层原理及区别对比分析

 更新时间:2025年12月01日 09:16:33   作者:Tan_Ying_Y  
Java 序列化和反射是 Java 中两个不同维度的机制,序列化聚焦对象的持久化与传输,反射聚焦类 / 对象的动态访问与操作,二者底层原理和应用场景差异显著,以下从底层原理、核心特性、区别对比展开解析,本文介绍Java 序列化和Java反射的底层原理及区别,感兴趣的朋友一起看看吧

Java 序列化与反射:底层原理与核心区别

Java 序列化和反射是 Java 中两个不同维度的机制,序列化聚焦对象的持久化与传输,反射聚焦类 / 对象的动态访问与操作,二者底层原理和应用场景差异显著,以下从底层原理、核心特性、区别对比展开解析:

一、Java 序列化:底层原理与机制

1. 定义与核心目标

序列化是将对象的状态信息(属性值)转换为字节序列的过程,反序列化则是将字节序列恢复为对象的过程。核心目标是实现对象的持久化(如存文件)、网络传输(如 RPC 通信)或跨进程共享。

2. 底层原理

(1)序列化的核心流程
  • 标记可序列化:类需实现java.io.Serializable接口(标记接口,无方法,仅标识类可被序列化);
  • 对象状态转换:JVM 通过序列化机制遍历对象的非静态属性(static、transient 修饰的属性不序列化),将属性值转换为字节序列;
  • 处理引用关系:若对象引用其他可序列化对象,会递归序列化引用对象,通过serialVersionUID保证序列化与反序列化的类版本一致性。
(2)关键细节
  • serialVersionUID:类的版本号,序列化时写入字节序列,反序列化时校验版本号是否一致,不一致则抛出InvalidClassException
  • transient 关键字:修饰的属性不参与序列化(如敏感数据、临时状态);
  • 自定义序列化:通过重写writeObject()/readObject()方法自定义序列化逻辑(如加密敏感属性);
  • Externalizable 接口:替代Serializable,需手动实现writeExternal()/readExternal(),完全控制序列化过程。
(3)底层实现(JVM 层面)

序列化由ObjectOutputStream实现,底层通过反射获取对象的类信息和属性值,按特定格式(如魔数、版本号、类名、属性类型 / 值)写入字节流;反序列化由ObjectInputStream实现,读取字节流并反射创建对象、恢复属性值。

3. 示例代码

import java.io.*;
// 实现Serializable接口
class User implements Serializable {
    private static final long serialVersionUID = 1L; // 版本号
    private String name;
    private transient int age; // transient修饰,不序列化
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}
public class SerializationDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 序列化:对象→字节序列(存文件)
        User user = new User("Alice", 20);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"));
        oos.writeObject(user);
        oos.close();
        // 反序列化:字节序列→对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"));
        User deserializedUser = (User) ois.readObject();
        ois.close();
        System.out.println(deserializedUser); // 输出:User{name='Alice', age=0}(age未序列化)
    }
}

二、Java 反射:底层原理与机制

1. 定义与核心目标

反射是指程序在运行时动态获取类的信息(如类名、属性、方法),并动态调用对象的方法、访问属性的机制。核心目标是打破封装,实现对类 / 对象的动态操作(如框架的灵活扩展)。

2. 底层原理

(1)反射的核心基础
  • Class 对象:每个类加载后,JVM 会为其创建一个Class对象(存储类的元数据:属性、方法、构造器等),反射通过Class对象访问类的信息;
  • 类加载机制:反射依赖类加载器(ClassLoader)加载类,可通过Class.forName()对象.getClass()类名.class获取Class对象。
(2)反射的核心流程
  • 获取 Class 对象:通过三种方式获取目标类的Class实例;
  • 访问类成员:通过Class对象的方法(如getFields()getMethods()getConstructors())获取属性、方法、构造器的Field/Method/Constructor对象;
  • 动态操作:通过Field.set()/get()访问属性值,Method.invoke()调用方法,Constructor.newInstance()创建对象(可突破访问修饰符限制,如访问 private 成员)。
(3)底层实现(JVM 层面)

JVM 在类加载时生成Class对象,存储在方法区(元空间),反射通过本地方法(native)调用 JVM 的底层接口,直接访问Class对象的元数据,绕过编译期的访问检查(如通过setAccessible(true)打破封装)。

3. 示例代码

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    private void sayHello() {
        System.out.println("Hello, " + name);
    }
}
public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 1. 获取Class对象
        Class<?> personClass = Person.class;
        // 2. 通过反射创建对象(调用构造器)
        Constructor<?> constructor = personClass.getConstructor(String.class, int.class);
        Object person = constructor.newInstance("Bob", 25);
        // 3. 访问private属性
        Field nameField = personClass.getDeclaredField("name");
        nameField.setAccessible(true); // 打破封装
        System.out.println("Name: " + nameField.get(person)); // 输出:Name: Bob
        // 4. 调用private方法
        Method sayHelloMethod = personClass.getDeclaredMethod("sayHello");
        sayHelloMethod.setAccessible(true);
        sayHelloMethod.invoke(person); // 输出:Hello, Bob
    }
}

三、序列化与反射的核心区别

维度Java 序列化Java 反射
核心目标对象的持久化、传输(状态保存与恢复)运行时动态访问 / 操作类 / 对象(打破封装)
底层聚焦对象状态的字节转换类元数据的动态访问
依赖机制实现Serializable接口,JVM 序列化规则依赖Class对象,反射 API(java.lang.reflect
操作对象对象的属性值(非静态、非 transient)类的属性、方法、构造器等成员
访问权限仅访问可序列化的属性(受修饰符限制)可突破访问修饰符(setAccessible(true)
应用场景分布式通信(RPC)、对象持久化(文件 / 数据库)框架开发(Spring/IOC、MyBatis)、动态代理、工具类(如 JSON 解析)
性能开销序列化 / 反序列化需遍历对象引用,开销中等反射需绕过编译期检查,性能低于直接调用(可通过缓存优化)
版本兼容性依赖serialVersionUID保证版本一致无版本问题,依赖类加载的元数据

四、关联与总结

  • 关联:序列化底层依赖反射获取对象的类信息和属性值;反射可用于自定义序列化逻辑(如通过反射遍历属性实现自定义序列化)。
  • 核心区别:序列化是 “对象状态的转换与恢复”,反射是 “类 / 对象的动态访问与操作”;序列化解决对象的传输与持久化问题,反射解决程序的动态性与灵活性问题。

理解二者的关键在于:序列化关注对象的状态,反射关注类的结构,二者虽底层都依赖 JVM 的类元数据,但目标和应用场景完全不同。

到此这篇关于Java 序列化和Java反射的底层原理以及区别?的文章就介绍到这了,更多相关java序列化和反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何获取所有spring管理的bean

    如何获取所有spring管理的bean

    这篇文章主要介绍了如何获取所有spring管理的bean,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot整合Ehcache3的实现步骤

    SpringBoot整合Ehcache3的实现步骤

    本文主要介绍了SpringBoot整合Ehcache3的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket

    Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket

    这篇文章主要介绍了Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java GC 机制与内存分配策略详解

    Java GC 机制与内存分配策略详解

    这篇文章主要介绍了Java GC 机制与内存分配策略详解的相关资料,需要的朋友可以参考下
    2017-02-02
  • Mybatis-plus使用TableNameHandler分表详解(附完整示例源码)

    Mybatis-plus使用TableNameHandler分表详解(附完整示例源码)

    这篇文章主要介绍了Mybatis-plus使用TableNameHandler分表详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 深入剖析Spring如何解决循环依赖

    深入剖析Spring如何解决循环依赖

    循环依赖(Circular Dependency)是指两个或多个Bean相互依赖,形成一个闭环的情况,本文将和大家深入探讨一下Spring如何解决循环依赖,需要的可以参考下
    2025-04-04
  • Java Predicate接口定义详解

    Java Predicate接口定义详解

    Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值,这篇文章主要介绍了Java Predicate接口的定义及示例代码,需要的朋友可以参考下
    2025-04-04
  • java遍历properties文件操作指南

    java遍历properties文件操作指南

    在java项目开发过程中,使用properties文件作为配置基本上是必不可少的,有很多如系统配置信息,java如何遍历properties文件呢,本文将详细介绍,希望可以帮助到您
    2012-11-11
  • SpringBoot集成Neo4j的详细教程

    SpringBoot集成Neo4j的详细教程

    Spring Boot 提供了对 Neo4j 的良好支持,使得开发者可以更方便地使用图数据库,通过使用 Spring Data Neo4j,开发者可以轻松地进行数据访问、操作以及管理,本文将详细介绍如何在 Spring Boot 应用中集成 Neo4j,需要的朋友可以参考下
    2024-11-11
  • 详解如何自定义parallelStream线程池

    详解如何自定义parallelStream线程池

    这篇文章主要为大家介绍了如何自定义parallelStream的线程池实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论