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类加载及双亲委派模型

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

相关推荐
j***63081 小时前
Springboot项目中线程池使用整理
java·spring boot·后端
likuolei1 小时前
Eclipse 创建 Java 接口
java·数据库·eclipse
q***54751 小时前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
a***56061 小时前
Spring Boot接收参数的19种方式
java·spring boot·后端
z***75152 小时前
SpringBoot集成MQTT客户端
java·spring boot·后端
q***69772 小时前
java进阶1——JVM
java·开发语言·jvm
码力码力我爱你2 小时前
C++静态变量依赖关系
java·jvm·c++
q***76662 小时前
Java_ElasticSearch(ES)——分布式搜索引擎
java·elasticsearch·搜索引擎
o***59272 小时前
解决 IntelliJ IDEA 中 Tomcat 日志乱码问题的详细指南
java·tomcat·intellij-idea