5月18日总结

概述

反射(Reflection)机制是指在运行时动态地获取类的信息以及操作类的成员(字段、方法、构造函数等)的能力。通过反射,我们可以在编译时期未知具体类型的情况下,通过运行时的动态查找和调用。 虽然 Java 是静态的编译型语言,但是反射特性的加入,提供一种直接操作对象外的另一种方式,让 Java 具备的一些灵活性和动态性,我们可以通过本篇文章来详细了解它
为什么需要反射 ?

Java 需要用到反射的主要原因包括以下几点:

运行时动态加载,创建类:Java中的类是在编译时加载的,但有时希望在运行时根据某些条件来动态加载和创建所需要类。反射就提供这种能力,这样的能力让程序可以更加的灵活,动态
动态的方法调用:根据反射获取的类和对象,动态调用类中的方法,这对于一些类增强框架(例如 Spring 的 AOP),还有安全框架(方法调用前进行权限验证),还有在业务代码中注入一些通用的业务逻辑(例如一些日志,等,动态调用的能力都非常有用
获取类的信息:通过反射,可以获取类的各种信息,如类名、父类、接口、字段、方法等。这使得我们可以在运行时检查类的属性和方法,并根据需要进行操作

一段示例代码

以下是一个简单的代码示例,展示基本的反射操作:

import java.lang.reflect.Method;

public class ReflectionExample {
public static void main(String[] args) {
// 假设在运行时需要调用某个类的方法,但该类在编译时未知
String className = "com.example.MyClass";

    try {
        // 使用反射动态加载类
        Class<?> clazz = Class.forName(className);

        // 使用反射获取指定方法
        Method method = clazz.getMethod("myMethod");

        // 使用反射创建对象
        Object obj = clazz.newInstance();

        // 使用反射调用方法
        method.invoke(obj);

    } catch (ClassNotFoundException e) {
        System.out.println("类未找到:" + className);
    } catch (NoSuchMethodException e) {
        System.out.println("方法未找到");
    } catch (IllegalAccessException | InstantiationException e) {
        System.out.println("无法实例化对象");
    } catch (Exception e) {
        System.out.println("其他异常:" + e.getMessage());
    }
}

}

在这个示例中,我们假设在编译时并不知道具体的类名和方法名,但在运行时需要根据动态情况来加载类、创建对象并调用方法。使用反射机制,我们可以通过字符串形式传递类名,使用 Class.forName() 动态加载类。然后,通过 getMethod() 方法获取指定的方法对象,使用 newInstance() 创建类的实例,最后通过 invoke() 方法调用方法。
使用场景

技术再好,如果无法落地,那么始终都是空中楼阁,在日常开发中,我们常常可以在以下的场景中看到反射的应用:

框架和库:许多框架和库使用反射来实现插件化架构或扩展机制。例如,Java 的 Spring 框架使用反射来实现依赖注入(Dependency Injection)和 AOP(Aspect-Oriented Programming)等功能。
ORM(对象关系映射):ORM 框架用于将对象模型和关系数据库之间进行映射。通过反射,ORM 框架可以在运行时动态地读取对象的属性和注解信息,从而生成相应的 SQL 语句并执行数据库操作。
动态代理:动态代理是一种常见的设计模式,通过反射可以实现动态代理。动态代理允许在运行时创建代理对象,并拦截对原始对象方法的调用。这在实现日志记录、性能统计、事务管理等方面非常有用
反射调试工具:在开发和调试过程中,有时需要查看对象的结构和属性,或者动态调用对象的方法来进行测试。反射提供了一种方便的方式来检查和操作对象的内部信息,例如使用getDeclaredFields()获取对象的所有字段,或使用getMethod()获取对象的方法
单元测试:在单元测试中,有时需要模拟或替换某些对象的行为,以便进行有效的测试。通过反射,可以在运行时创建对象的模拟实例,并在测试中替换原始对象,以便控制和验证测试的行为

Class 对象

Class 对象是反射的第一步,我们先从 Class 对象聊起,因为在反射中,只要你想在运行时使用类型信息,就必须先得到那个 Class 对象的引用,他是反射的核心,它代表了Java类的元数据信息,包含了类的结构、属性、方法和其他相关信息。通过Class对象,我们可以获取和操作类的成员,实现动态加载和操作类的能力。

常见的获取 Class 对象的方式几种:

// 使用类名获取
Class<?> clazz = Class.forName("com.example.MyClass");

// 使用类字面常量获取
Class<?> clazz = MyClass.class;

// 使用对象的 getClass() 方法获取
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();

posted @ 2023-05-22 00:03  lmyyyy  阅读(13)  评论(0)    收藏  举报