多态仅提供统一接口调用机制,而反射负责运行时类型识别、实例化与装配;框架通过反射穿透类型边界,结合注解和泛型元数据实现对象映射与依赖注入。

Java 多态机制本身不负责对象映射与装载,它只提供“父类引用指向子类对象”的运行时行为;真正实现统一对象映射与装载的,是框架(如 Spring、MyBatis)在多态表象下,用反射穿透类型边界、动态识别真实类型并完成实例化与装配。
多态提供统一接口,反射决定实际类型
多态让上层代码面向抽象编程(比如 Service 接口),但框架启动时并不知道具体哪个实现类会被加载。这时反射介入:扫描 classpath 下所有标注 @Service 的类,通过 Class.forName("com.example.UserServiceImpl") 加载字节码,再用 clazz.getDeclaredConstructor().newInstance() 创建实例——这个过程完全绕开了编译期的类型绑定,也无需 instanceof 判断。
关键点在于:
• 多态定义了“能调什么”(方法签名一致)
• 反射决定了“实际是谁”(运行时解析全限定名、加载、实例化)
反射突破多态限制,获取真实结构信息
当一个 Object 或泛型容器(如 List<Animal>)里存着多个子类对象(Dog、Cat),多态只能调用 Animal 声明的方法。而框架需要做属性填充、序列化、AOP 增强等操作,就必须知道每个对象的真实类:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 调用
obj.getClass()获取运行时 Class 对象 - 用
clazz.getDeclaredFields()扫描所有字段(包括 private) - 对标注
@Autowired或@Value的字段,用field.setAccessible(true)并赋值 - 即使字段在父类中声明、子类中继承,反射也能准确定位到实际归属类
统一映射依赖于反射+注解+类型擦除补偿
Java 泛型在运行时被擦除,但框架仍需按类型注入 Bean。Spring 的解决方案是结合反射与注解元数据:
立即学习“Java免费学习笔记(深入)”;
- 解析
@Autowired字段时,不仅看声明类型(如UserService),还通过field.getGenericType()获取带泛型的实际类型(如Map<String, User>) - 扫描所有候选 Bean 后,用反射检查其
getClass().isAssignableFrom(requiredType)是否满足继承关系 - 若存在多个匹配,再依据
@Primary或名称匹配进一步筛选——整个过程不依赖编译期类型,只依赖运行时 Class 结构
装载过程由反射驱动,多态仅用于后续调用
以 Spring IoC 容器为例,Bean 的生命周期中:
- 装载阶段:读取 XML 或注解配置 → 反射加载类 → 反射调用构造器 → 反射设置字段/方法 → 反射触发初始化回调
- 使用阶段:外部代码拿到的是接口引用(多态),但内部持有的是具体子类实例(反射创建)
- 代理增强(如事务):用反射获取目标方法签名,再基于
InvocationHandler或 CGLIB 生成代理——代理对象仍实现相同接口,保持多态一致性

















