从 0 学 Java(22):用反射实现类的动态加载,理解 “运行时绑定”
·
用反射实现类的动态加载与理解"运行时绑定"
1. 核心概念
- 反射机制:Java 在运行时动态获取类信息(字段/方法/构造器等)并操作对象的能力
- 运行时绑定:方法调用在运行时根据实际对象类型确定执行逻辑(区别于编译时绑定)
- 动态加载:程序运行时才加载并初始化类(而非编译时)
2. 反射实现动态加载
import java.lang.reflect.*;
interface Animal {
void speak();
}
class Dog implements Animal {
@Override
public void speak() {
System.out.println("汪汪!");
}
}
class Cat implements Animal {
@Override
public void speak() {
System.out.println("喵喵!");
}
}
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 动态获取类名(实际应用中可来自配置文件/用户输入等)
String className = args.length > 0 ? args[0] : "Dog";
// 1. 动态加载类
Class<?> clazz = Class.forName(className);
// 2. 创建实例(运行时绑定发生点)
Animal animal = (Animal) clazz.getDeclaredConstructor().newInstance();
// 3. 动态调用方法
Method speakMethod = clazz.getMethod("speak");
speakMethod.invoke(animal);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 关键代码解析
-
动态加载类
Class.forName("类全限定名")在运行时加载类,如:Class<?> clazz = Class.forName("Dog"); // 加载Dog类 -
运行时创建实例
// 获取无参构造器并实例化 Constructor<?> constructor = clazz.getDeclaredConstructor(); Animal animal = (Animal) constructor.newInstance(); -
动态方法调用
Method method = clazz.getMethod("speak"); // 获取方法对象 method.invoke(animal); // 执行方法(运行时绑定)
4. 运行时绑定原理
当调用 animal.speak() 时:
- 编译时仅检查
Animal接口是否有speak()方法 - 运行时 JVM 通过虚方法表查找实际对象类型(
Dog/Cat) - 根据对象实际类型调用对应方法实现
数学表示(方法调用过程):
$$ \text{调用地址} = \text{VTable}[\text{对象类型}][\text{方法索引}] $$
5. 执行示例
# 运行动态加载Dog类
java ReflectionDemo Dog
输出:汪汪!
# 运行动态加载Cat类
java ReflectionDemo Cat
输出:喵喵!
6. 应用场景
- 框架开发(如 Spring 的依赖注入)
- 插件系统(运行时加载扩展模块)
- 动态代理(AOP 实现)
- 序列化/反序列化工具
关键理解:反射打破了"编译时确定类型"的限制,通过
Class对象在运行时动态解析类型信息,配合虚方法表实现真正的多态行为。
更多推荐
所有评论(0)