Java 反射(Reflection)完整讲解
·
Java 反射(Reflection)完整讲解
一、什么是反射
反射机制:程序运行时,动态获取类的全部信息(类名、成员变量、方法、构造器),并调用对象方法、操作属性。
正常开发:编译期就确定类、方法,直接 new 对象() 调用;
反射:运行时才解析类,无需提前硬编码。
二、反射核心类(java.lang.reflect)
Class:代表类/接口的字节码对象,反射入口Constructor:构造方法Method:成员方法Field:成员变量
三、获取 Class 对象的三种方式
// 1. 对象.getClass()(已有实例)
Person p = new Person();
Class<?> clazz1 = p.getClass();
// 2. 类名.class(静态获取,推荐)
Class<?> clazz2 = Person.class;
// 3. Class.forName("全类名")(最常用,配置文件加载类)
Class<?> clazz3 = Class.forName("com.test.Person");
四、反射操作全流程示例
实体类
public class Person {
public String name;
private int age;
// 无参构造
public Person(){}
// 私有有参构造
private Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公有方法
public void show(String msg) {
System.out.println("show:" + msg);
}
// 私有方法
private void secret() {
System.out.println("私有方法");
}
}
1. 通过反射创建对象
Class<?> clazz = Person.class;
// 1)无参构造创建对象
Object obj1 = clazz.newInstance(); // JDK9+废弃,推荐Constructor
// 标准写法
Constructor<?> con1 = clazz.getConstructor();
Person p1 = (Person) con1.newInstance();
// 2)获取私有构造,暴力访问
Constructor<?> con2 = clazz.getDeclaredConstructor(String.class, int.class);
con2.setAccessible(true); // 关闭权限校验
Person p2 = (Person) con2.newInstance("张三", 20);
2. 反射操作成员变量 Field
Person p = new Person();
Class<?> clazz = p.getClass();
// 获取公有变量
Field nameField = clazz.getField("name");
nameField.set(p, "李四");
System.out.println(nameField.get(p));
// 获取私有变量
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(p, 18);
System.out.println(ageField.get(p));
3. 反射调用方法 Method
Person p = new Person();
Class<?> clazz = p.getClass();
// 公有方法
Method show = clazz.getMethod("show", String.class);
show.invoke(p, "测试消息");
// 私有方法
Method secret = clazz.getDeclaredMethod("secret");
secret.setAccessible(true);
secret.invoke(p);
五、关键方法区分
getXXX():只获取public(父类公有也能拿到)- getField / getMethod / getConstructor
getDeclaredXXX():获取本类所有(public/private/protected),不包含父类- getDeclaredField / getDeclaredMethod / getDeclaredConstructor
六、setAccessible(true) 暴力反射
私有构造、私有变量、私有方法默认无法访问;setAccessible(true) 关闭Java权限检查,运行时强行操作私有成员。
七、反射优缺点
优点
- 高度灵活:运行时动态创建对象、调用方法,框架底层核心(Spring、Mybatis)
- 解耦:通过配置文件全类名加载类,不用硬编码 new
缺点
- 性能差:绕过编译期优化,执行速度慢
- 破坏封装:暴力访问私有属性/方法,违背面向对象封装
- 安全性问题:可绕过权限校验,部分高安全环境禁用反射
- 代码繁琐,可读性差
八、反射典型应用场景
- Spring IoC:通过反射创建Bean、注入属性
- ORM框架(Mybatis):反射映射数据库字段与实体属性
- 注解解析、动态代理
- 配置文件读取类,动态实例化
- 单元测试框架JUnit动态调用测试方法
九、面试核心考点
- 获取Class对象三种方式区别
- getXXX 和 getDeclaredXXX 的区别
- setAccessible(true)作用
- 反射优缺点
- 反射为什么性能低
- 反射破坏封装的体现
更多推荐


所有评论(0)