JAVA反射机制

一.简介:

我们平时开发时,可以在编译前看到源码,可以清楚的知道类中的方法和属性,当编译为.class文件后,程序自己是看不到类的内部结构的,但是反射不一样,它使得程序在拥有在运行时自我审视的能力,就像一把万能钥匙,在运行时获取类的所有信息,包括名字属性方法构造函数,也可以在运行时动态创建实例,还能在运行时调用对象的方法,修改对象的属性。

二.反射获取class对象:

方式1:通过类名.class获取

方式2:通过Class类的forName()方法

方式3:通过对象调用getClass()方法

三.反射获取类的所有信息,包括调用其私有构造函数及私有方法

先搞个类,字段和方法包括构造函数全部为私有化

java 复制代码
public class SingletonDemo {
    private static SingletonDemo singletonDemo = null;

    private static final String test = "我是私有字段";

    private SingletonDemo() {
    }
    private String testMethod() {
        return "我是私有方法";
    }
}

开始调用测试

java 复制代码
 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //根据完全限定名通过反射获取类
        Class clz = Class.forName("org.example.demoproject.test.SingletonDemo");
        //获取类名
        System.out.println("完全限定名为:" + clz.getName());
        System.out.println("简单的类名为:" + clz.getSimpleName());
        //获取包名
        System.out.println("该类的包名为" + clz.getPackage().getName());
        System.out.println("======================================================");

        //获取成员变量
        Field[] fieldArray = clz.getDeclaredFields();
        for (Field field : fieldArray) {
            System.out.println("该类成员变量(字段)名为:" + field);
        }
        System.out.println("=======================================================");

        //获取成员方法及使用
        Method[] methodArray = clz.getDeclaredMethods();
        System.out.println("测试调用私有构造函数,并通过其获取的实例调用其私有构造方法");
        for (Method method : methodArray) {
            // 获取私有构造方法
            Constructor<SingletonDemo> constructor = SingletonDemo.class.getDeclaredConstructor();
            // 将私有构造函数设置为可访问
            constructor.setAccessible(true);
            // 创建实例
            SingletonDemo instance = constructor.newInstance();

            // 将私有方法设置为可访问
            method.setAccessible(true);
            Object invoke = method.invoke(instance);
            System.out.println(invoke);
        }
    }

输出结果

反射的部分方法:

clz.getName() :

返回类的完全限定名,包括包名,例如 "org.example.demoproject.test.SingletonDemo"。
clz.getSimpleName():

返回类的简单名称,不包括包名,例如 "SingletonDemo"。
clz.getPackage().getName():

返回类所属的包名,例如 "org.example.demoproject.test"。
clz.getDeclaredFields() :

返回一个 Field 数组,包含了类声明的所有字段(包括私有字段)。
clz.getDeclaredMethods() :

返回一个 Method 数组,包含了类声明的所有方法(包括私有方法)。

四.Spring将反射用在哪:

1.最典型的就是Sping的依赖注入(DI),例如@Autowired通过反射获取对象并进行属性注入
2.控制反转IOC容器:动态创建对象:扫描配置类后获取Class对象,调用构造方法创建实例
3.扫描注解:通过Class.getAnnotations()获取类、方法、字段上的注解,例如@Component、@Service
4.AOP面向切面编程:基于反射和JDK动态代理或CGLIB字节码增强,实现事务管理、日志记录、权限控制等横切关注点
5.Spring MVC框架‌:反射调用控制器方法处理请,实现请求映射和参数绑定

五.反射的优缺点缺点:

优点:

动态性,灵活性极高,是所有主流框架的基石

缺点:

1.性能开销大:

因为它绕开了编译器优化,且需要在运行时动态查找类的信息,整个过程很耗时,反射调用比直接调用‌慢10-100倍‌,在极端情况下可达‌340倍‌
2.安全风险:

①破坏封装性:可绕过访问限制操作私有成员‌

②漏洞利用:攻击者可能通过反射注入恶意代码(如内存马)或触发反序列化漏洞执行命令‌

③类型混淆:动态调用未校验的类名可能导致非预期行为‌
3.代码可读性下降:

反射操作(如动态调用方法)会降低代码可读性,增加维护难度‌

因此反射是一把双刃剑,用好了是神器,滥用就是灾难,咱们平时开发时能不用就不要用


上一篇 >>>>> SpringBoot类加载及双亲委派模型

看千遍想万遍,还得动手练一练,量变才能产生质变

相关推荐
mldong4 小时前
一个 App,十三套后端:手机审批端 uni-jeeflow-app 开源了
java·架构
tqs_123455 小时前
MySQL RR隔离级别死锁|Gap间隙锁、临键锁,订单并发范围查询死锁根因方案
java
逆境不可逃5 小时前
Pi Agent 学习笔记:多个工具怎样并行执行
java
Flynt6 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet6 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
星云API技术支持6 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
niucloud-admin6 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
海宇AI7 小时前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化车抵贷核保网关
java·人工智能·架构·自动化
Bs_MoneyMagnet8 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
cfm_29149 小时前
单例模式详解
java