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():暴力反射
相关推荐
小锋java12341 小时前
【技术专题】Spring AI 2.0 - Advisors —— 拦截器模式增强AI能力
java·人工智能
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第56题】【JVM篇】第16题:JVM有哪些垃圾收集器?
java·开发语言·jvm·面试
二哈赛车手2 小时前
新人笔记---简易版AI实现以图搜图功能
java·人工智能·笔记·spring·ai
夕除2 小时前
spring boot 6
java·spring boot·后端
johnrui2 小时前
JUC之AQS
java·开发语言·jvm
Full Stack Developme2 小时前
Spring 模块介绍
java·后端·spring
多敲代码防脱发2 小时前
Spring进阶(BeanFactory与ApplicationContext)
java·数据库·spring boot·后端·spring
吴声子夜歌3 小时前
Java——反射
java·反射
JAVA面经实录9173 小时前
完整版JVM 深度学习体系(二)
java·jvm