什么是反射?
- 反射核心概念:反射是获取类信息的能力,包括类名、方法名、变量、构造器等。
- 类信息存储在方法区,反射可以通过三种方式获取类对象:类名.class、Class.forName和对象名.getClass
- 类信息都是存储在类对象当中
-
获取类信息是为了使用类信息
反射获取变量示例图:

一 如何获取Class的实例?
-
Class<T>获取类型参数对应的
Class对象的方法。三种获取方式:Class<String> clazz2 = String.class; // 直接通过一个类的静态变量class获取 、 Class<?> clazz3 = "abc".getClass(); // 通过对象实例 //如果知道一个类的完整类名,可以通过静态方法Class.forName()获取 Class<?> clazz = Class.forName("java.lang.String"); // 通过全限定名一个类的Class实例是在类加载时被创建的,而一个类只会被加载一次一个类的Class实例是在类加载时被创建的,而一个类只会被加载一次,(即Class实例在JVM中是唯一的),所以它的hashCode()值也是唯一的 :

输出结果

二 成员变量与成员方法
一、操作成员变量(Fields)
1. 获取字段对象
getField(String name):获取公有字段(包括继承的公有字段)
getDeclaredField(String name):获取任意声明的字段(包括私有、protected,不包括继承字段)
2. 读写字段值
set(Object obj, Object value):设置字段值
get(Object obj):获取字段值
代码示例
// 获取 PUBLIC 字段(包括父类继承的)
Field publicField = clazz.getField("fieldName");
// 获取任意访问权限的字段(仅当前类声明,不包括继承)
Field anyField = clazz.getDeclaredField("fieldName");
// 获取所有声明的字段(私有/公有/保护,不包括继承)
Field[] allFields = clazz.getDeclaredFields();
三 操作成员方法(Methods)
1. 获取方法对象
getMethod(String name, Class<?>... parameterTypes):获取公有方法
getDeclaredMethod(String name, Class<?>... parameterTypes):获取任意声明的方法(包括私有)
2. 调用方法
-
invoke(Object obj, Object... args):调用方法-
obj:方法所属对象实例 -
args:方法参数
-
代码示例
// 获取 PUBLIC 方法(包括父类继承的)
Method publicMethod = clazz.getMethod("methodName", parameterTypes);
// 获取任意访问权限的方法(仅当前类声明)
Method anyMethod = clazz.getDeclaredMethod("methodName", parameterTypes);
// 获取所有声明的方法(私有/公有/保护)
Method[] allMethods = clazz.getDeclaredMethods();
四 Constructor类
- 得到类的所有构造方法
Constructor constructors[]=Class.forName("java.lang.String").getConstructors();//先得到类对应的字节码对象,再得到构造方法
得到类中某个具体的构造方法,在getConstructor中传入参数类型所对应的字节码
Constructor constructor=Class.forName("java.lang.String").getCondtructor(String.class)//得到String 类的 带有一个String类型参数的构造方法
Method method = clazz.getDeclaredMethod("methodName", int.class); // 方法名 + 参数类型
暴力反射
-
setAccessible(true):使私有/受保护字段可访问(关键步骤)
1 如果构造方法、普通方法、字段 被private(私有)修饰,默认情况下,在该类的外部是 不允许被访问的,如果使用暴力反射,即使被private修饰也可以进行操作
2 通常只在测试、框架开发等特殊场景下使用
-
如果不设置,访问私有字段会抛出
IllegalAccessException
使用示例:
-
获取私有成员
// 获取私有字段 Field privateField = clazz.getDeclaredField("privateField"); // 获取私有方法 Method privateMethod = clazz.getDeclaredMethod("privateMethod", parameterTypes); // 获取私有构造方法 Constructor<?> privateConstructor = clazz.getDeclaredConstructor(parameterTypes); -
突破访问限制(关键步骤)
// 解除访问检查(暴力核心) privateField.setAccessible(true); // 字段 privateMethod.setAccessible(true); // 方法 privateConstructor.setAccessible(true); // 构造方法
-
执行操作
// 访问/修改私有字段值 Object value = privateField.get(targetObject); // 获取值 privateField.set(targetObject, newValue); // 修改值 // 调用私有方法 Object result = privateMethod.invoke(targetObject, args); // 实例化私有构造 Object instance = privateConstructor.newInstance(args);
五 示例详解
构造器操作与对象创建
通过反射获取并调用构造器创建对象:
public static void main(String[] args) throws Exception {
// 获取Student类对象
Class clazz = Student.class;
// 1. 无参构造器创建对象
Constructor c1 = clazz.getDeclaredConstructor();
Student s1 = (Student) c1.newInstance();
// 2. 带int参数构造器
Constructor c2 = clazz.getDeclaredConstructor(int.class);
Student s2 = (Student) c2.newInstance(10);
// 3. 私有构造器(暴力反射)
Constructor c3 = clazz.getDeclaredConstructor(String.class, int.class, int.class);
c3.setAccessible(true); // 解除私有封装
Student s3 = (Student) c3.newInstance("张三", 15, 180);
}
成员变量操作
动态访问和修改字段值(含私有字段):
// 获取并设置私有字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // 暴力反射解除私有限制
nameField.set(s1, "小花");
System.out.println("s1.name = " + nameField.get(s1));
// 操作公共字段
Field ageField = clazz.getField("age");
ageField.set(s3, 20);
System.out.println("s3.age = " + ageField.get(s3));
成员方法调用
动态调用各类方法(含私有方法):
// 调用公共方法
Method startMethod = clazz.getMethod("start", String.class, Integer.class);
startMethod.invoke(s3, "李四", 30);
// 调用私有方法
Method runMethod = clazz.getDeclaredMethod("run", int.class);
runMethod.setAccessible(true);
runMethod.invoke(s2, 5);
// 调用默认可见性方法
Method stopMethod = clazz.getDeclaredMethod("stop", float.class, char.class);
stopMethod.invoke(s1, 3.5f, 'A');
辅助Student类定义
class Student {
// 字段定义
public int age;
private String name;
protected int height;
String sex;
// 构造器
public Student() {}
public Student(int age) { this.age = age; }
private Student(String name, int age, int height) {
this.name = name;
this.age = age;
this.height = height;
}
// 方法定义
public void start(String name, Integer age) {
System.out.println(name + "开始学习,年龄:" + age);
}
private void run(int speed) {
System.out.println("私有方法调用:以速度" + speed + "跑步");
}
void stop(float time, char unit) {
System.out.println("停止学习于" + time + unit);
}
}
执行结果验证
s1.name = 小花 s3.age = 20 李四开始学习,年龄:30 私有方法调用:以速度5跑步 停止学习于3.5A
反射核心要点
-
暴力反射:通过
setAccessible(true)解除私有成员封装 -
动态操作:运行时获取类信息,无需编译期依赖
-
应用场景:
-
框架设计(如Spring IOC)
-
动态代理
-
注解处理器
-
通用工具类开发
-
1190

被折叠的 条评论
为什么被折叠?



