简介

Java 反射(Reflection)是 Java 语言中的一个功能强大的特性,允许程序在运行时检查或修改自身的结构(类、方法、字段等)。通过反射,开发者可以在程序运行时动态地访问类和对象的属性、调用方法,甚至修改其行为。反射主要用于框架开发、工具类库、动态代理等场景。

Java 反射的常见用途:

  1. 在运行时获取类信息:可以获取一个类的名称、构造方法、字段、方法、父类等信息。
  2. 动态创建对象:通过反射动态地创建类的实例,甚至可以调用私有构造方法。
  3. 调用方法:可以在运行时调用对象的公开或私有方法。
  4. 访问和修改字段:可以在运行时访问或修改对象的公开或私有字段。
  5. 动态代理:使用反射机制可以实现动态代理,特别是 AOP(面向切面编程)和其他框架中的功能。

常用的反射类

  • Class<?>:代表一个类,提供了很多用于获取类信息的方法,比如 getDeclaredFields()getDeclaredMethods()
  • Constructor<?>:代表构造方法,可以通过反射创建对象。
  • Field:代表类的字段,可以用来访问和修改对象的字段。
  • Method:代表类的方法,可以用来调用对象的方法。

反射的使用

  1. 获取 Class 对象:
  • 通过类名:Class.forName("com.example.MyClass")
  • 通过对象:object.getClass()
  • 通过类字面量:MyClass.class
  1. 获取构造方法:
  • Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
  • Constructor<T>[] getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
  • Constructor<?>[] getDeclaredConstructors(Class<?>... parameterTypes):返回单个构造方法对象

成员方法:

  • T newInstance(Object... initargs):根据指定的构造方法创建对象
  • setAccessible(boolean flag):设置为 true,代表取消访问检查
  1. 获取字段:
  • Field[] getFields():返回所有公共成员变量对象的数组
  • Field[] getDelaredFields:返回所有成员变量对象的数组
  • Field getField(String name):返回单个公共成员变量对象
  • Field getDelaredFiedl(String name):返回单个成员变量对象

成员方法:

  • void set(Object obj, Object value):赋值
  • Object get(Object obj):获取值
  • setAccessible(boolean flag):设置为 true,代表取消访问检查
  1. 获取方法:
  • Method[] getMethods:返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDelaredMethods:放回成员方法对象的数组,不包括继承的
  • Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
  • Method getDelaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象

成员方法:

  • Object invoke(Object obj, Object... args):运行方法
  • setAccessible(boolean flag):设置为 true,代表取消访问检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.lang.reflect.*;

public class ReflectionExample {
private String name;

public ReflectionExample() {
this.name = "Initial Name";
}

private void printName() {
System.out.println("Name: " + this.name);
}

public static void main(String[] args) throws Exception {
// 1. 获取Class对象
Class<?> clazz = ReflectionExample.class;

// 2. 创建对象实例
ReflectionExample instance = (ReflectionExample) clazz.getDeclaredConstructor().newInstance();

// 3. 访问私有字段
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(instance, "Updated Name");

// 4. 调用私有方法
Method printNameMethod = clazz.getDeclaredMethod("printName");
printNameMethod.setAccessible(true);
printNameMethod.invoke(instance); // 输出:Name: Updated Name
}
}

在实际开发中,反射的性能相对较低,因此不推荐频繁使用。它主要用于框架开发或当需要动态操作对象时才会使用。