Java 反射机制动态创建对象详解课件(初学者版)
一、课程信息
学习目标
- 理解反射的核心作用:动态操作类的信息
- 掌握反射创建对象的三大核心步骤
- 能通过反射突破构造器权限,实现灵活创建
- 理解反射的优缺点及适用场景,避免滥用
二、课程导入:生活中的 "动态"
🌰 场景类比:万能工厂
- 传统工厂:提前知道产品类型,用
new
创建(如new Car()
) - 反射工厂:根据 "图纸名称" 动态生产(如根据配置文件中的类名创建对象)
三、反射基础:Class 对象
1. 反射的本质
在运行时获取类的信息,并动态创建对象、调用方法
核心:通过Class
对象获取类的元数据
2. 获取 Class 对象的三种方式
方式 1:Class.forName("全类名")
(最常用)
Class<?> clazz = Class.forName("com.example.Student");
方式 2:类名.class
(编译时已知类)
Class<Student> clazz = Student.class;
方式 3:对象.getClass()
(运行时获取对象类型)
Student stu = new Student();
Class<?> clazz = stu.getClass();
3. 案例:打印类信息
class Student {
private String name;
public Student(String name) { this.name = name; }
}
public class ReflectionDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1
Class<?> clazz1 = Class.forName("Student"); // 需导入包或全类名
// 方式2
Class<Student> clazz2 = Student.class;
// 方式3
Student stu = new Student("张三");
Class<?> clazz3 = stu.getClass();
System.out.println("类名:" + clazz1.getName()); // Student
System.out.println("是否为接口:" + clazz1.isInterface()); // false
}
}
四、反射创建对象的核心步骤
🔧 步骤 1:获取构造器
获取无参构造器
Constructor<?> constructor = clazz.getConstructor();
获取有参构造器
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
获取私有构造器(需暴力反射)
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true); // 忽略权限检查
🔧 步骤 2:创建对象
无参构造器创建
Object obj = constructor.newInstance();
有参构造器创建
Object obj = constructor.newInstance("张三", 18);
🔍 完整案例:动态创建学生对象
class Student {
private String name;
private int age;
// 无参构造器(默认public)
public Student() {}
// 私有有参构造器
private Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ReflectionCreateObject {
public static void main(String[] args) throws Exception {
Class<Student> clazz = Student.class;
// 方式1:调用无参构造器
Student stu1 = clazz.newInstance(); // JDK9+已过时,改用构造器
// 方式2:通过构造器创建(推荐)
Constructor<Student> publicConstructor = clazz.getConstructor();
Student stu2 = publicConstructor.newInstance();
// 方式3:调用私有构造器
Constructor<Student> privateConstructor = clazz.getDeclaredConstructor(String.class, int.class);
privateConstructor.setAccessible(true); // 暴力访问
Student stu3 = privateConstructor.newInstance("李四", 20);
}
}
五、反射 vs new
关键字
特性 | 反射 | new 关键字 |
---|---|---|
创建时机 | 运行时动态决定 | 编译时确定 |
构造器权限 | 可突破私有构造器 | 只能调用 public 构造器 |
灵活性 | 高(根据类名字符串创建) | 低(需硬编码类名) |
性能 | 低(涉及额外校验) | 高 |
六、实际应用案例
🔥 案例 1:根据配置文件创建对象(模拟框架)
场景:从config.properties
读取类名,动态创建日志处理器
# config.properties
logger.class=com.example.FileLogger
代码实现:
import java.io.FileInputStream;
import java.util.Properties;
interface Logger {
void log(String msg);
}
class FileLogger implements Logger {
public void log(String msg) {
System.out.println("文件日志:" + msg);
}
}
public class ReflectionConfig {
public static void main(String[] args) throws Exception {
// 读取配置文件
Properties props = new Properties();
props.load(new FileInputStream("config.properties"));
String className = props.getProperty("logger.class");
// 反射创建对象
Class<?> clazz = Class.forName(className);
Logger logger = (Logger) clazz.newInstance();
logger.log("反射创建对象成功");
}
}
🔥 案例 2:通用对象复制工具
需求:将一个对象的属性值复制到另一个同类型对象
public static void copy(Object source, Object target) throws Exception {
Class<?> clazz = source.getClass();
// 获取所有public字段
Field[] fields = clazz.getFields();
for (Field field : fields) {
Object value = field.get(source);
field.set(target, value);
}
}
// 使用
Student stu1 = new Student("张三", 18);
Student stu2 = new Student();
copy(stu1, stu2); // stu2的属性被复制
七、初学者必避的 3 大陷阱
陷阱 1:类名错误导致ClassNotFoundException
Class.forName("com.example.UnknownClass"); // 类不存在时抛异常
陷阱 2:构造器参数类型不匹配
clazz.getConstructor(int.class); // 实际构造器是(String.class)
陷阱 3:忽略权限检查
Constructor<?> constructor = clazz.getDeclaredConstructor();
// 未调用setAccessible(true)直接调用newInstance()
// 私有构造器会抛IllegalAccessException
八、课堂练习
练习 1:反射创建私有构造器对象
任务:为Singleton
类(私有构造器)实现反射创建,绕过单例限制
练习 2:动态调用方法
需求:通过反射调用String
类的toUpperCase()
方法
九、课程总结
知识图谱:
反射创建对象
↳ 核心步骤:获取Class→获取构造器→newInstance()
↳ 暴力反射:setAccessible(true)突破权限
↳ 应用场景:框架开发、插件系统、通用工具
口诀记忆:
“反射反射真神奇,运行时刻探类密,
Class 对象是钥匙,构造方法来创建,
私有权限也能破,框架开发离不了!”
十、课后作业
必做 1:反射实现工厂模式
需求:用反射优化工厂模式,根据类名字符串创建对象
必做 2:分析 Spring 的 Bean 创建
任务:查阅 Spring 源码,说明BeanFactory
如何用反射创建 Bean