一、什么是反射
反射(Reflection) 是Java语言的一个重要特性,它允许程序在运行时动态地获取、访问类的所有信息。
本质:JVM在加载.class文件时,会在堆内存中生成一个唯一的Class对象,这个对象包含了类的所有元数据(属性、方法、构造方法等)。反射正是通过操作这些元数据来突破编译期的语法检查限制。
二、Class类
1. 是什么?
Class对象是类的"说明书",是反射机制的根源。每个类在JVM中都有且只有一个Class对象。
2. 获得Class对象的三种方式
// 方式1:通过类名.class
Class<User> clazz1 = User.class;
// 方式2:通过对象.getClass()
User user = new User();
Class<? extends User> clazz2 = user.getClass();
// 方式3:通过Class.forName("全类名")
Class<?> clazz3 = Class.forName("com.example.User");
三、Constructor类
1. 是什么?
描述构造方法的类,通过它可以创建类的实例。
2. 获得Constructor对象的方法
Class<User> clazz = User.class;
// 获取所有公共构造方法
Constructor<?>[] publicConstructors = clazz.getConstructors();
// 获取所有构造方法(包括私有)
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
// 获取指定公共构造方法
Constructor<User> publicConstructor = clazz.getConstructor(String.class, int.class);
// 获取指定构造方法(包括私有)
Constructor<User> privateConstructor = clazz.getDeclaredConstructor(String.class);
3. 常用方法
// 创建实例
Constructor<User> constructor = clazz.getConstructor(String.class, int.class);
User user = constructor.newInstance("张三", 25);
// 访问私有构造方法
Constructor<User> privateConstructor = clazz.getDeclaredConstructor(String.class);
privateConstructor.setAccessible(true); // 设置可访问
User privateUser = privateConstructor.newInstance("私有构造");
四、Field类
1. 是什么?
描述属性的类,通过它可以读取、修改属性的值。
2. 获得Field对象的方法
// 获取所有公共成员变量
Field[] publicFields = clazz.getFields();
// 获取所有成员变量
Field[] allFields = clazz.getDeclaredFields();
// 获取指定公共成员变量
Field publicField = clazz.getField("publicFieldName");
// 获取指定成员变量
Field privateField = clazz.getDeclaredField("privateFieldName");
3. 常用方法
User user = new User();
// 获取字段值
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
Object value = nameField.get(user);
// 设置字段值
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(user, 30);
五、Method类
1. 是什么?
描述方法的类,通过它可以调用方法。
2. 获得Method对象的方法
// 获取所有公共方法
Method[] publicMethods = clazz.getMethods();
// 获取所有方法
Method[] allMethods = clazz.getDeclaredMethods();
// 获取指定公共方法
Method publicMethod = clazz.getMethod("methodName", String.class, int.class);
// 获取指定方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod", String.class);
3. 常用方法
User user = new User();
// 调用公共方法
Method publicMethod = clazz.getMethod("publicMethod", String.class);
Object result1 = publicMethod.invoke(user, "参数");
// 调用私有方法
Method privateMethod = clazz.getDeclaredMethod("privateMethod", String.class);
privateMethod.setAccessible(true);
Object result2 = privateMethod.invoke(user, "私有方法参数");
六、Annotation类
1. 是什么?
描述注解的类,通过它可以判断某个元素是否添加了注解、读取注解的属性值。
2. 获得Annotation对象的方法
// 获取类上的所有注解
Annotation[] classAnnotations = clazz.getAnnotations();
// 获取类上的所有注解(包括继承的)
Annotation[] declaredClassAnnotations = clazz.getDeclaredAnnotations();
// 获取方法上的指定注解
Method method = clazz.getMethod("testMethod");
Annotation methodAnnotation = method.getAnnotation(MyAnnotation.class);
3. 常用方法
// 判断是否包含指定注解
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
// 获取注解实例
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
// 读取注解属性值
String value = annotation.value();
int number = annotation.number();
}
反射应用场景
-
框架开发:Spring、MyBatis等框架大量使用反射
-
动态代理:AOP编程的基础
-
注解处理器:编译时和运行时的注解处理
-
序列化和反序列化:JSON、XML等数据格式的转换
-
单元测试:测试私有方法
注意事项
-
性能问题:反射操作比直接调用慢,频繁使用需考虑性能
-
安全问题:反射可以突破封装性,需要谨慎使用
-
可维护性:过度使用反射会降低代码的可读性和可维护性
反射是Java语言强大灵活性的体现,合理使用可以大大提高程序的灵活性和扩展性,但也要注意其带来的性能开销和安全隐患。
561



被折叠的 条评论
为什么被折叠?



