Java八股之反射

张开发
2026/4/17 21:48:25 15 分钟阅读

分享文章

Java八股之反射
1. 什么是反射在 Java 的世界里我们通常是在编译期就确定了一个对象的类型然后new出它的实例。但在很多高级框架如 Spring、MyBatis中程序在编译时根本不知道要加载哪个类只有在运行时才能动态地获取类信息并创建对象。这种“在运行状态中对于任意一个类都能知道它的所有属性和方法对于任意一个对象都能调用它的任意方法和属性” 的能力就是 Java 的反射机制。简单来说反射让 Java 变成了一种“准动态语言”赋予了代码极强的扩展性。2. 核心 APIClass 对象要理解反射首先要理解Class对象。在 Java 中万物皆对象。类Class本身也是一个对象。当类加载器将一个.class文件加载到内存时JVM 会为这个类创建一个java.lang.Class实例。获取 Class 对象的三种方式Class.forName(全类名)最常用常用于配置文件中读取类名。类名.class常用于编译期已知类的情况。对象.getClass()已有实例时使用。3. 实战演练反射能干什么光说不练假把式我们通过代码来看看反射的四大金刚构造方法、成员变量、成员方法。假设我们有一个普通的实体类UserpublicclassUser{privateStringname;privateintage;publicUser(){}privateUser(Stringname){this.namename;}publicvoidsayHello(){System.out.println(Hello, I am name);}privatevoidsecretMethod(){System.out.println(这是一个私有方法);}}场景一暴力反射破解私有反射最强大的地方在于它可以无视访问修饰符private。// 1. 获取 Class 对象Class?clazzClass.forName(com.example.User);// 2. 获取私有构造方法并创建对象Constructor?constructorclazz.getDeclaredConstructor(String.class);constructor.setAccessible(true);// 暴力访问取消权限检查Objectuserconstructor.newInstance(张三);// 3. 调用私有方法MethodsecretMethodclazz.getDeclaredMethod(secretMethod);secretMethod.setAccessible(true);// 暴力访问secretMethod.invoke(user);// 输出这是一个私有方法// 4. 修改私有属性FieldnameFieldclazz.getDeclaredField(name);nameField.setAccessible(true);nameField.set(user,李四);// 把名字改成李四注意在实际开发中setAccessible(true)是非常敏感的操作它破坏了封装性但在框架开发如 ORM 映射中却是必不可少的。4. 灵魂拷问反射的优缺点在面试中经常被问到“反射有什么缺点”不要只回答“慢”。优点解耦与扩展性这是反射最大的价值。Spring 的 IOC 容器就是利用反射根据配置文件创建 Bean实现了代码的零侵入。通用性可以编写与具体类无关的通用代码如 JSON 解析工具 FastJSON/Gson。缺点性能开销反射涉及动态解析类型JVM 无法对其进行优化如内联缓存速度比直接调用慢。安全限制反射需要绕过访问检查如果运行在安全管理器SecurityManager环境下可能会受限。破坏泛型反射可以绕过泛型检查向ArrayListInteger中添加字符串。5. 进阶反射真的很慢吗这是一个常见的误区。在 JDK 1.7 之前反射确实非常慢。但在现代 JDK 中如果关闭了访问检查即调用了setAccessible(true)JVM 会对其进行优化性能损耗其实是可以接受的。结论除非是在极高并发的热点代码路径上如循环几百万次否则反射的性能损耗通常不是瓶颈开发效率和解耦的收益远大于性能损耗。6. 总结反射是 Java 框架的基石。作为业务开发我们可能不需要天天写反射代码但理解它有助于我们读懂 Spring、MyBatis 的源码写出更优雅的代码。以下是反射常用到的方法Class.forName(String className)根据类名获取对应的 Class 对象。getClass()获取对象的运行时类型。getMethod(String name, Class?… parameterTypes)获取指定方法名和参数类型的方法。getField(String name)获取指定名称的字段。newInstance()使用默认的构造函数创建实例。newInstance(Object… initargs)使用指定参数类型和值的构造函数创建实例。invoke(Object obj, Object… args)调用指定对象的方法。最简回答Java 的反射机制是指在运行时动态地获取类的信息并操作类或对象的能力。通过反射我们可以在编译时无法确定的情况下通过类名获取类的实例、获取类的字段、方法、构造函数等信息并且可以在运行时调用这些方法或访问这些字段。

更多文章