Java反射技术

一、概述

反射:

  • 是针对Class对象进行操作的
  • 是一种针对这个Class对象解剖的技术(构造器,成员方法,成员变量)

简单说,就是对运行时获取编译后的class文件,通过反射技术,动态的去获取构造,成员变量,成员方法
反射技术实现要素及其核心思想: Class对象

利用class对象去动态获取所需的构造,成员变量,成员方法


二、获取Class的方式

1.使用类名.class -> 详看使用场景3

java 复制代码
类名.class; // 直接通过类名获取类的class对象

2.使用Class.forName(),好处:在运行程序的时候,动态加载类的class字节码到内存,然后生成对象 -> 详看使用场景1

java 复制代码
Class.forName("类的全限定名[带有包名的类]"); // 如com.jdbc.mysql.Driver
// 全限定名 = 顶部package后地址+类名

3.使用对象名.getClass() -> 详看使用场景2

java 复制代码
对象名.getClass(); // 直接通过对象名来创建class对象,用于创建具体对象后

易错纠正:不存在 对象名.class(),正确写法为 对象.getClass()


三、使用场景

场景1:读取配置文件,使用了获取类输入流来读取配置,再使用Class.forName()动态加载类
先创建好一个配置文件student.ini在src目录下

properties 复制代码
className=com.mysql.jdbc.Driver

之后在Main类中

java 复制代码
Properties prop = new Properties();  
prop.load(Main.class.getClassLoader().getResourceAsStream("bean.properties"));//读配置 
String className = prop.getProperty("className");//通过Key找value
Class.forName(className); // 动态的加载Class对象

场景2:当方法中是形参传递的是对象需要获取class的时候

java 复制代码
public void method(Student stu){
	Class<Student> stucls = stu.getClass();
}

场景3:当明确类名的时候

java 复制代码
类名.class;直接得到class对象

对于当前对象获取class,可以直接使用this.getClass()来替代类名.class


四、通过类加载器得到构造器(Constructor)

成员方法说明

成员方法1.得到public构造器对象

java 复制代码
class对象.getConstructor(); // 只能获取public无参构造
class对象.getConstructor(参数类型.class); // 获取public有参构造

成员方法2.得到任意权限构造器对象(包含私有)

java 复制代码
class对象.getDeclaredConstructor(); 

成员方法3:调用构造创建对象

java 复制代码
构造器对象.newInstance();

案例1:使用构造器创建Student对象

先创建javabean的对象Student

java 复制代码
@Data  // get、set、toString
@AllArgsConstructor // 全参构造
@NoArgsConstructor  // 无参构造
public class Student {  
    private String name;  
    private int age;  
}

1)通过无参构造创建对象

java 复制代码
// 得到class的对象
Class<? extends Student> aClass = new Student().getClass();
// 得到无参构造器
Constructor<? extends Student> constructor = aClass.getConstructor();

// 通过构造器创建对象
Student student = constructor.newInstance(); 
student.setName("zhangsan");
student.setAge(13);

System.out.println(student.toString());

2)通过带参构造创建对象

java 复制代码
Class<? extends Student> aClass = new Student().getClass();  
// 得到带参构造器,并指明构造的数据类型
Constructor<? extends Student> constructor = aClass.getConstructor(String.class,int.class);  

// 传入参数创建对象
Student student = constructor.newInstance("张三",12);  

System.out.println(student.toString());

3)暴力反射获取私有构造器

java 复制代码
// 获取私有构造器
Constructor<? extends Student> decConstructor = aClass.getDeclaredConstructor();
// 关闭权限校验,暴力访问
decConstructor.setAccessible(true);
// 创建对象
Student student = decConstructor.newInstance();

五、反射操作成员变量(Field)

核心方法区分

  1. getField("变量名")仅获取public公开成员变量
  2. getDeclaredField("变量名")获取所有权限成员变量(private/protected/public)

核心操作方法

java 复制代码
field.setAccessible(true); // 暴力反射,解除私有权限限制
field.set(对象, 赋值); // 给对象的成员变量赋值
field.get(对象); // 获取对象的成员变量值

完整案例:反射操作私有成员变量

java 复制代码
// 1.获取Class对象
Class<Student> studentClass = Student.class;
// 2.获取私有成员变量name
Field nameField = studentClass.getDeclaredField("name");
// 3.暴力解除权限
nameField.setAccessible(true);

// 4.创建空对象
Student student = studentClass.newInstance();
// 5.给私有变量赋值
nameField.set(student, "李四");
// 6.获取变量值
String name = (String) nameField.get(student);

System.out.println(name);

六、反射操作成员方法(Method)

核心方法区分

  1. getMethod("方法名",参数类型.class)仅获取public公开方法
  2. getDeclaredMethod("方法名",参数类型.class)获取所有权限方法(包含私有)

核心执行方法

java 复制代码
method.setAccessible(true); // 暴力反射(私有方法必须加)
method.invoke(对象, 方法参数); // 执行方法,返回方法返回值

完整案例:反射调用get/set方法、自定义方法

java 复制代码
// 1.获取Class对象
Class<Student> studentClass = Student.class;
Student student = studentClass.newInstance();

// 2.获取setName公开方法
Method setName = studentClass.getMethod("setName", String.class);
// 3.执行set方法赋值
setName.invoke(student, "王五");

// 4.获取getName公开方法并执行
Method getName = studentClass.getMethod("getName");
String resName = (String) getName.invoke(student);

System.out.println(resName);

私有方法调用案例

java 复制代码
// 获取私有方法
Method privateMethod = studentClass.getDeclaredMethod("私有方法名");
// 解除权限
privateMethod.setAccessible(true);
// 执行私有方法
privateMethod.invoke(student);

七、反射核心必背规则(考试/面试高频)

  1. getXXX() :只能获取 public 权限的构造、变量、方法
  2. getDeclaredXXX() :可以获取 所有权限(private/默认/protected/public)
  3. 所有私有资源操作必须加:setAccessible(true),否则报错权限不足
  4. 反射全部API均抛出编译时异常,代码必须try-catch捕获
  5. Class.forName() 常用于框架配置文件加载、解耦
  6. 反射最大特点:编译期不知道类型,运行期动态操作

八、反射所有核心API汇总

1. Class类常用方法

  • 获取构造器:getConstructor() / getDeclaredConstructor()
  • 获取成员变量:getField() / getDeclaredField()
  • 获取成员方法:getMethod() / getDeclaredMethod()
  • 创建对象:newInstance()

2. Constructor构造器

  • newInstance():实例化对象

3. Field成员变量

  • set():赋值
  • get():取值
  • setAccessible():暴力反射

4. Method成员方法

  • invoke():执行方法
  • setAccessible():暴力反射
相关推荐
用户298698530141 分钟前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao37 分钟前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿42 分钟前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
鹤望兰6751 小时前
字节跳动国际支付-后端开发-三面面经
java
Flittly1 小时前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
RainCity1 小时前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
吃饱了得干活17 小时前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器
java·spring cloud
lwx5728019 小时前
探秘InnoDB:搞懂它的内存、线程、磁盘与日志刷盘策略
java·后端
Flynt20 小时前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
plainGeekDev21 小时前
Activity 间传值 → Navigation 参数
android·java·kotlin