说明:Java 的反射(Reflection)机制允许程序在运行时动态获取类的信息并操作类或对象的方法、字段、构造器等。其核心原理是通过 Class 对象 在运行时解析类的结构。
一、反射的核心原理
-
类加载与 Class 对象
1)当 JVM 加载一个 .class 文件时,会为每个类生成一个唯一的 Class 对象(位于堆内存中)。
2)Class 对象包含类的完整结构信息(方法、字段、构造器、父类、接口等)。 -
反射入口
1)通过 Class 对象,可以动态获取类的元数据,并创建对象、调用方法、访问字段等。
二、获取 Class 对象的四种方式
- 通过类名.class(最安全,性能最好)
说明:知道具体类名
Class alunbarClass = TargetObject.class;
但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取Class对象
- 通过对象.getClass()
Employee e = new Employee();
Class alunbarClass2 = e.getClass();
Class.forName(className)方法,内部实际调用的是一个native方法 forName0(className, true, ClassLoader.getClassLoader(caller), caller);
- 通过 Class.forName(“全限定类名”)(常用,需处理异常)
Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
- 通过类加载器ClassLoader.LoadClass(“全限定类名”)
class clazz = ClassLoader.LoadClass("cn.javaguide.TargetObject");
三、代码示例
- 创建一个我们要使用反射操作的类 TargetObject:
package cn.javaguide;
public class TargetObject {
private String value;
public TargetObject() {
value = "JavaGuide";
}
public void publicMethod(String s) {
System.out.println("I love " + s);
}
private void privateMethod() {
System.out.println("value is " + value);
}
}
- 使用反射操作这个类的方法以及参数
package cn.javaguide;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
/**
* 获取TargetObject类的Class对象并且创建TargetObject类实例
*/
Class<?> tagetClass = Class.forName("cn.javaguide.TargetObject");
TargetObject targetObject = (TargetObject) tagetClass.newInstance();
/**
* 获取所有类中所有定义的方法
*/
Method[] methods = tagetClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
/**
* 获取指定方法并调用
*/
Method publicMethod = tagetClass.getDeclaredMethod("publicMethod",
String.class);
publicMethod.invoke(targetObject, "JavaGuide");
/**
* 获取指定参数并对参数进行修改
*/
Field field = tagetClass.getDeclaredField("value");
//为了对类中的参数进行修改我们取消安全检查
field.setAccessible(true);
field.set(targetObject, "JavaGuide");
/**
* 调用 private 方法
*/
Method privateMethod = tagetClass.getDeclaredMethod("privateMethod");
//为了调用private方法我们取消安全检查
privateMethod.setAccessible(true);
privateMethod.invoke(targetObject);
}
}
输入出内容:
publicMethod
privateMethod
I love JavaGuide
value is JavaGuide
四、反射的优缺点
优点 | 缺点 |
---|---|
动态加载类,提高代码灵活性 | 性能开销大(比直接调用慢约 10-20 倍) |
突破封装性(可操作私有成员) | 破坏封装性,可能导致安全问题 |
实现通用框架(如 Spring) | 代码可读性降低,调试困难 |
文档代码参考:Java 反射(详细 含示例)