Java-反射与注解:框架的基石

第一部分:反射(Reflection)

反射 是指在程序运行时,可以动态地获取一个类的完整信息(包括类名、构造方法、方法、字段等),并且能动态地创建对象、调用方法、修改字段。

它让 Java 从“静态语言”获得了部分“动态语言”的能力。

  • 正常使用方式:编写代码就确定使用的类,通过new()实例化获取类对象进行操作
  • 反射使用方式:在运行时才决定要操作哪个类,先获取类的Class对象,再通过Class对象获取构造器,最后通过newInstance()获取对象进行操作
    • Class对象:
      • 每个Java 类在编译后都会生成xx.class文件
      • 每个xx.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("全限定类名") 获取
// (最常用,支持动态加载)
Class<?> clazz3 = Class.forName("com.example.Person");

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)

注解是一种“标记”或“元数据”,它本身不实现业务逻辑,可以附加在类、方法、字段等上面

注解的解析和执行,通常依赖于反射或其他编译时工具。

内置注解(重点)
注解 作用 检查时机
@Override 标记方法是重写父类方法。编译器会检查是否满足重写规则。 编译期
@Deprecated 标记某个元素已过时,不建议使用。使用时会编译警告。 编译期
@SuppressWarnings 抑制编译器警告。 编译期
@FunctionalInterface 标记接口是函数式接口(只有一个抽象方法)。 编译期

元注解

(注解的注解)

 
元注解 作用 常用值
@Target 指定自定义注解可以应用于何处(类、方法、字段等)。 ElementType.TYPE(类)、ElementType.METHODElementType.FIELD
@Retention 指定注解在哪个阶段有效。

RetentionPolicy.SOURCE(源码)

CLASS(编译后)、RUNTIME(运行时,反射需要)

@Documented 表示该注解会出现在Javadoc中。 -
@Inherited 表示该注解可以被继承(子类继承父类的注解)。 -
自定义注解
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可以标记为测试方法,测试框架运行测试时才会运行。

posted @ 2026-08-07 10:26  Fēngwèi  阅读(3)  评论(0)    收藏  举报