Java-反射与注解:框架的基石
第一部分:反射(Reflection)
反射 是指在程序运行时,可以动态地获取一个类的完整信息(包括类名、构造方法、方法、字段等),并且能动态地创建对象、调用方法、修改字段。
它让 Java 从“静态语言”获得了部分“动态语言”的能力。
- 正常使用方式:编写代码就确定使用的类,通过new()实例化获取类对象进行操作
- 反射使用方式:在运行时才决定要操作哪个类,先获取类的Class对象,再通过Class对象获取构造器,最后通过newInstance()获取对象进行操作
- Class对象:
- 每个Java 类在编译后都会生成xx.class文件
- 每个xx.class文件都有对应的Class对象,获取Class对象就能获取类的全部信息
- 优点:动态灵活、可以编写通用的框架代码
- 缺点:性能开销、破坏封装性、可读性降低
- Class对象:
// 1. 获取Class对象 Class<?> clazz = Class.forName("com.example.Person"); // 2. 获取构造方法并创建对象 Constructor<?> constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("张三", 25); // 3. 获取并调用方法 Method method = clazz.getMethod("setName", String.class); method.invoke(obj, "李四"); // 4. 访问字段 Field field = clazz.getDeclaredField("name"); field.setAccessible(true); String name = (String) field.get(obj);
|
1、获取 Class 对象的三种方式(反射的入口) // 1. 通过类名.class 获取 Class<Person> clazz1 = Person.class; // 2. 通过对象.getClass() 获取 Person p = new Person(); Class<?> clazz2 = p.getClass(); // 3. 通过 Class.forName("全限定类名") 获取 |
2、通过反射获取类的"元数据"(信息) // 获取所有构造方法 Constructor<?>[] constructors = clazz.getConstructors(); // 获取所有方法(包括私有) Method[] methods = clazz.getDeclaredMethods(); // 获取所有字段(包括私有) Field[] fields = clazz.getDeclaredFields(); // 获取特定的方法或字段 Method method = clazz.getMethod("methodName", String.class); Field field = clazz.getDeclaredField("fieldName"); |
3、通过反射执行"动态操作" // 1. 创建对象 Constructor<?> constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("张三", 25); // 2. 调用方法 Method method = clazz.getMethod("setName", String.class); method.invoke(obj, "李四"); // 3. 访问字段(包括私有字段) Field field = clazz.getDeclaredField("name"); field.setAccessible(true); // 暴力反射,突破 private 限制 String name = (String) field.get(obj); field.set(obj, "王五"); |
第二部分:注解(Annotation)
注解是一种“标记”或“元数据”,它本身不实现业务逻辑,可以附加在类、方法、字段等上面。
注解的解析和执行,通常依赖于反射或其他编译时工具。
| 内置注解(重点) |
|
|||||||||||||||
|
元注解 (注解的注解) |
|
|||||||||||||||
| 自定义注解 |
import java.lang.annotation.*; // 1. 声明注解,指定作用目标和保留策略 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) // 必须为 RUNTIME,才能用反射读取 public @interface MyAnnotation { // 定义注解属性(类似方法) String value() default ""; // 属性名:value int priority() default 1; String description() default "无描述"; } // 使用自定义注解,现在只是一个安静的“标签” // 需要一个注解处理器,通常通过反射在运行时读取注解信息,然后根据这些信息执行不同的逻辑。 @MyAnnotation(value = "测试类", description = "用于演示注解") public class AnnotatedClass { @MyAnnotation(value = "测试方法", priority = 5) public void testMethod() { System.out.println("执行测试方法"); } } |
框架的基石:框架在运行时,通过反射读取类上的注解,然后根据注解信息决定如何执行代码,比如@Test可以标记为测试方法,测试框架运行测试时才会运行。
本文来自博客园,作者:Fēngwèi,转载请注明原文链接:https://www.cnblogs.com/fengwei-blogs/p/22301795

浙公网安备 33010602011771号