java中反射详解

本文详细介绍了Java反射的基本概念,包括如何通过Class、Constructor、Field和Method类进行运行时类型操作,如获取类信息、构造对象、访问成员变量和调用方法。

反射

什么是反射?

反射是Java语法的一种高级特性,在“运行期间”对Java的类型信息进行检查、操作处理。

例如:加载JDBC驱动类、MyBatis动态处理resultType、Spring根据配置信息创建Bean对象等使用场景。

常见操作

  1. 获取Class类型信息
  2. 执行构造方法创建对象
  3. 调用实例方法
  4. 通过成员变量保存值和获取值

反射中常用类

1.Class类

Class对象用于保存一个类的类型信息,它是反射的入口操作。

获取Class对象的三张方式
类名
Class bookClass = Book.class;
通过forName()方法
Class cls2 = Class.forName("com.apesource.Demo.Book");
通过对象
Class cls3 = new Book().getClass();
2.Constructor类

代表一个类中的构造方法(构造器),用于创建“目标”对象

获取Constructor构造方法的方式
  • 获取无参构造方法 Class对象.getConstructor()
  • 获取有参构造方法 Class对象.getConstructor(Class…)
//获取无参构造方法
Constructor constr1 = cls2.getConstructor();
//获取有参构造方法
Constructor constr2 = cls2.getConstructor(String.class,String.class,double.class,int.class);
执行Constructor构造方法的方式
  • 执行无参构造方法 Constructor对象.newInstance()
  • 执行有参构造方法 Constructor对象.newInstance(值…)
//执行无参构造方法
Object obj2 = constr1.newInstance();
//执行有参构造方法
Object obj3 = constr2.newInstance("西游","吴承恩",120.5,500);
3.Field类

代表一个类中的成员变量(字段),用于为“目标对象”保存值和获取值

获取Field成员变量的方式
获取所有成员变量
  • public修饰的成员变量 Class对象.getFields()
  • public\private修饰的成员变量 Class对象.getDeclaredField()
Field[] fields = cl.getFields();

field.setAccessible(true);
Field[] fields = cl.getDeclaredFields();
获取指定成员变量
  • public修饰的成员变量 Class对象.getFields(成员变量名称)

  • public\private修饰的成员变量 Class对象.getDeclaredField(成员变量名称)

    Field field = cl.getField("fieldName");
    
    field.setAccessible(true);
    Field field = cl.getDeclaredField("fieldName");
    
使用Field成员变量的方式
  • Field对象.setXXX(目标对象,值)
//通过成员变量赋值
field.setAccessible(true);
field.set(obj,"葫芦娃");
4.Method类

代表一个类中的方法,用于调用执行该方法

获取Method方法的方式
  • Class对象.getMethod()
  • Class对象.getMethods()
//获取该类的指定方法
Method method = cl.getMethod(methodName, String.class);

//获取该类的方法
Method[] methods = cls.getMethods();

for(Method method : methods) {

    System.out.println(method);			
    System.out.println("修饰符:"+method.getModifiers());
    System.out.println("返回值类型:"+method.getReturnType());
    System.out.println("参数列表:");			
    for(Parameter c :  method.getParameters()){				
        System.out.print(c);
    }
    System.out.println();
    System.out.println("方法名:"+method.getName());			
    System.out.println();
}
执行Method方法的方式
  • Method对象.invoke(目标对象,方法参数)
//执行
Object invoke = method.invoke(obj, UUID.randomUUID().toString());
其他
//获取该类的接口信息
Class[] interfaces = cls.getInterfaces();

//获取该类的包信息
Package package1 = cls.getPackage();

//获取该类的父类信息
Class superclass = cls.getSuperclass();
<think>好的,我现在需要详细解析Java反射机制,并提供使用示例。首先,我需要回顾反射的基本概念和原理。根据引用[1]和[2],反射允许程序在运行时检查和操作类的结构和行为,动态获取类的信息,访问属性和方法。这涉及到Class类、Method、Field、Constructor等核心API,如引用[4]提到的。 接下来,要解释反射的用途,比如框架开发、动态代理,特别是Spring中通过XML配置装载Bean的例子(引用[3])。然后需要详细说明如何使用反射,包括获取Class实例、创建对象、访问字段、调用方法等步骤,每个部分都需要代码示例。 还需要注意性能影响,反射可能比直接调用慢,但现代JVM优化了这点,不过频繁使用仍需谨慎。应用场景部分要强调动态加载和灵活性,如插件系统或配置驱动的架构。 用户可能的问题包括反射的优缺点、如何提高反射性能、在Spring中的具体应用,以及安全性问题。要确保回答覆盖这些方面,并结构清晰,分步骤讲解。 最后,检查示例代码的正确性,确保使用中文,数学公式正确应用$...$格式,独立公式用$$...$$。引用标识要自然添加,如引用[1]、[2]等。确保回答符合系统级指令的所有要求,包括生成相关问题,并正确格式化代码块。</think>### Java 反射机制详解 #### 一、反射的基本概念 Java 反射机制允许程序在**运行时**动态获取类的信息(如方法、属性、构造器等),并操作对象或调用方法,无需在编译时确定具体类[^1][^2]。这种能力使得框架和工具能够实现高度灵活的设计,例如 Spring 框架通过 XML 配置动态加载 Bean[^3]。 #### 二、反射的核心 API 1. **`java.lang.Class`**:表示类的元数据,反射操作的入口。 2. **`java.lang.reflect.Method`**:描述类的方法。 3. **`java.lang.reflect.Field`**:描述类的成员变量。 4. **`java.lang.reflect.Constructor`**:描述类的构造方法[^4]。 #### 三、反射的使用步骤 ##### 1. 获取 `Class` 对象 三种方式: - **`类名.class`**:`Class<User> clazz = User.class;` - **`对象.getClass()`**:`User user = new User(); Class<?> clazz = user.getClass();` - **`Class.forName("全限定类名")`**:`Class<?> clazz = Class.forName("com.example.User");` ##### 2. 创建对象实例 通过构造器实例化: ```java Constructor<?> constructor = clazz.getDeclaredConstructor(); Object obj = constructor.newInstance(); // 调用无参构造 ``` ##### 3. 操作字段 ```java Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); // 允许访问私有字段 nameField.set(obj, "Alice"); // 设置字段值 String name = (String) nameField.get(obj); // 获取字段值 ``` ##### 4. 调用方法 ```java Method method = clazz.getDeclaredMethod("setName", String.class); method.invoke(obj, "Bob"); // 调用 setName("Bob") ``` #### 四、示例代码 ```java public class User { private String name; public User() {} public void setName(String name) { this.name = name; } } public class ReflectionDemo { public static void main(String[] args) throws Exception { // 获取 Class 对象 Class<?> clazz = Class.forName("User"); // 创建实例 Object user = clazz.getDeclaredConstructor().newInstance(); // 设置私有字段 Field field = clazz.getDeclaredField("name"); field.setAccessible(true); field.set(user, "Charlie"); // 调用方法 Method method = clazz.getMethod("setName", String.class); method.invoke(user, "David"); } } ``` #### 五、性能与注意事项 - **性能影响**:反射操作比直接调用慢,因涉及动态解析和安全检查,可通过缓存 `Method` 或 `Field` 对象优化。 - **安全性**:反射可绕过访问限制(如私有方法),需谨慎使用。 - **典型场景**:动态代理、IDE 调试工具、Spring 框架的依赖注入。 #### 六、应用场景 1. **框架开发**:如 Spring 通过反射加载和管理 Bean。 2. **动态代理**:AOP 实现中动态生成代理类。 3. **序列化工具**:JSON 库通过反射解析对象字段。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值