Java 反射是指在运行时检查、获取和操作类的信息和对象的能力。通过反射机制,可以在运行时动态地获取类的结构信息(如字段、方法、构造函数等)、调用类的方法、创建对象实例等。反射机制为编写灵活、通用、可扩展的代码提供了支持,但同时也会增加代码的复杂性和性能开销。
以下是 Java 反射的主要概念和使用方法:
Class 类:Class 类是 Java 反射的核心类之一,它表示运行时类的信息。通过 Class 类可以获取类的结构信息(如字段、方法、构造函数等)、创建类的对象实例以及执行类的方法等操作。
获取 Class 对象:可以通过多种方式获取 Class 对象,包括使用类的 .class 属性、调用类的 getClass() 方法、使用 Class.forName() 方法等。
获取类的结构信息:通过 Class 对象可以获取类的字段、方法、构造函数等信息,包括获取公共字段、私有字段、静态字段、公共方法、私有方法、构造函数等。
创建对象实例:通过 Class 对象可以创建类的对象实例,包括通过默认构造函数、指定构造函数、无参构造函数等方式创建对象。
调用方法:通过 Method 类可以调用类的方法,包括调用公共方法、私有方法、静态方法等。可以使用 Method.invoke() 方法调用方法并传递参数。
操作字段:通过 Field 类可以操作类的字段,包括获取字段值、设置字段值等。可以使用 Field.get() 方法获取字段值,Field.set() 方法设置字段值。
操作构造函数:通过 Constructor 类可以操作类的构造函数,包括获取构造函数、创建对象实例等。可以使用 Constructor.newInstance() 方法创建对象实例。
动态代理:Java 反射还可以实现动态代理,即在运行时动态地创建代理对象,并在代理对象中实现对目标对象的方法调用,以实现额外的逻辑或功能。
适用场景:Java 反射通常用于需要在运行时动态地操作类和对象的场景,如编写通用的框架、库或工具、实现依赖注入、实现ORM(Object-Relational Mapping) 框架等。但需要注意,反射机制可能会降低代码的性能和安全性,因此应该谨慎使用,并考虑是否有更好的替代方案
反射示例
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 获取 Class 对象
Class<?> clazz = MyClass.class;
// 获取类的字段信息
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("字段名:" + field.getName() + ", 类型:" + field.getType());
}
// 获取类的方法信息
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("方法名:" + method.getName() + ", 返回类型:" + method.getReturnType());
}
// 获取类的构造函数信息
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("构造函数:" + constructor);
}
// 创建对象实例
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true); // 设置可访问私有构造函数
MyClass obj = (MyClass) constructor.newInstance("Hello", 123);
// 调用方法
Method method = clazz.getDeclaredMethod("printInfo");
method.setAccessible(true); // 设置可访问私有方法
method.invoke(obj);
// 操作字段
Field field = clazz.getDeclaredField("message");
field.setAccessible(true); // 设置可访问私有字段
String value = (String) field.get(obj);
System.out.println("字段值:" + value);
}
}
class MyClass {
private String message;
private int number;
private MyClass(String message, int number) {
this.message = message;
this.number = number;
}
private void printInfo() {
System.out.println("Message: " + message + ", Number: " + number);
}
}
JAVA动态代理示例,通过反射实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义接口
interface Subject {
void doSomething();
}
// 实现接口的类
class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("RealSubject: Doing something...");
}
}
// 实现 InvocationHandler 接口
class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在调用目标方法前添加额外的逻辑
System.out.println("Before method execution...");
// 调用目标方法
Object result = method.invoke(target, args);
// 在调用目标方法后添加额外的逻辑
System.out.println("After method execution...");
return result;
}
}
public class ProxyExample {
public static void main(String[] args) {
// 创建目标对象
RealSubject realSubject = new RealSubject();
// 创建动态代理对象
Subject proxy = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new DynamicProxy(realSubject)
);
// 调用代理对象的方法
proxy.doSomething();
}
}
在以前jdbc中,获取到数据库连接查询到数据,也是通过反射方式,获取类的字段信息,并从结果集中获取对应字段的值