一.简介:
我们平时开发时,可以在编译前看到源码,可以清楚的知道类中的方法和属性,当编译为.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类加载及双亲委派模型