简述Java 反射机制是指在程序运行状态中,对于任意一个类,都能获取其所有属性和方法;对于任意一个对象,都能调用其任意方法和属性。这种动态获取信息与动态调用对象方法的能力,就是 Java 反射机制的核心。 反射基础- RTTI(运行时类型识别) :区别于编译时已确定的类型,RTTI 能在运行时识别对象或类的信息,而反射是 RTTI 的重要实现方式。
- 反射的本质:将类的属性、方法、构造器等组件 “解剖” 为一个个可操作的对象,从而实现动态操作类的能力。
Class 类Java 中每个类或接口在 JVM 中都对应一个Class对象(包括基本数据类型和 void),它是反射的核心入口。 Class 类的特点- 是java.lang包下的 final 类,实现了多个接口。
- 构造方法为private,仅由 JVM 创建和加载,开发者无法手动实例化。
- 每个类在 JVM 中仅有一个对应的Class对象,全局唯一。
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement { // 源码片段:构造方法私有 private Class(ClassLoader loader) { classLoader = loader; }}
类加载机制- 编译:Java 文件编译为.class文件,包含类的完整信息。
- 加载:类加载器(ClassLoader)将.class文件加载到内存。
- 生成 Class 对象:JVM 为每个类创建唯一的Class对象,后续所有实例对象都基于该Class对象创建。
示意图逻辑: 本地 / 网络的.class文件 → 类加载器 → 内存生成唯一Class对象 → 基于Class对象创建多个实例对象。 反射的核心类库Java 反射主要依赖java.lang.Class类和java.lang.reflect包,其中关键类包括: - Constructor:类的构造方法
- Field:类的成员变量
- Method:类的成员方法
- Modifier:访问修饰符工具类
常用方法速查表方法 | 说明 | forName(String) | 通过全限定类名获取Class对象,立即加载并初始化类 | getClass() | 通过对象实例获取Class对象,返回实际类型 | getName() | 获取类的全限定名(含包名) | getSimpleName() | 获取类名(不含包名) | isXXX() | 判断类型(如isInterface()是否为接口,isEnum()是否为枚举) | getXXX() | 获取单个成员(如getField(String)获取 public 字段),含父类 public 成员 | getXXXs() | 获取成员数组(如getMethods()获取所有 public 方法),含父类 public 成员 | getDeclaredXXX() | 获取本类声明的单个成员(含私有),不含父类 | getDeclaredXXXs() | 获取本类声明的所有成员(含私有),不含父类 | newInstance() | 通过无参构造器创建实例(需类有默认构造器) |
获取 Class 对象的三种方式- 类名.class:通过类名直接获取,编译时确定类型。
- 对象.getClass () :通过实例对象获取,运行时确定实际类型。
- Class.forName (全限定类名) :通过类路径动态获取,适用于未知类型。
// 示例public class ReflectionDemo { public static void main(String[] args) throws ClassNotFoundException { // 方式1:类名.class Class<Student> clazz1 = Student.class; // 方式2:对象.getClass() Student student = new Student(); Class<? extends Student> clazz2 = student.getClass(); // 方式3:Class.forName() Class<?> clazz3 = Class.forName("com.example.Student"); }}
Constructor类用于获取和调用类的构造方法,支持访问私有构造器。 示例代码public class Student { private String name; public int age; public Student() {} public Student(int age) { this.age = age; } private Student(String name, int age) { this.name = name; this.age = age; }}// 反射操作构造器public class TestConstructor { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.example.Student"); // 调用无参构造器 Student s1 = (Student) clazz.newInstance(); // 调用public单参构造器 Constructor<?> c1 = clazz.getConstructor(int.class); Student s2 = (Student) c1.newInstance(18); // 调用私有构造器(需设置可访问) Constructor<?> c2 = clazz.getDeclaredConstructor(String.class, int.class); c2.setAccessible(true); // 解除私有访问限制 Student s3 = (Student) c2.newInstance("Tom", 20); }}
Field 类:操作成员变量Field类用于获取和修改类的成员变量,包括私有变量。 示例代码public class TestField { public static void main(String[] args) throws Exception { Class<?> clazz = Student.class; Student student = new Student(); // 获取public字段(含父类) Field ageField = clazz.getField("age"); ageField.set(student, 20); // 修改public字段 System.out.println(ageField.get(student)); // 输出:20 // 获取私有字段(仅本类) Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); // 解除私有限制 nameField.set(student, "Jerry"); System.out.println(nameField.get(student)); // 输出:Jerry }}
Method 类:操作成员方法Method类用于获取和调用类的成员方法,包括私有方法。 示例代码public class Student { private void showName() { System.out.println("Name: " + name); } public int getAge() { return age; }}// 反射操作方法public class TestMethod { public static void main(String[] args) throws Exception { Class<?> clazz = Student.class; Student student = new Student(); // 调用私有方法 Method showMethod = clazz.getDeclaredMethod("showName"); showMethod.setAccessible(true); showMethod.invoke(student); // 输出:Name: Jerry // 调用public方法 Method getMethod = clazz.getMethod("getAge"); int age = (int) getMethod.invoke(student); System.out.println("Age: " + age); // 输出:20 }}
反射的实际应用:Spring IOCSpring 的 IOC 容器核心依赖反射实现: - 扫描类路径下的@Component注解类,通过Class.forName()获取Class对象。
- 解析类的属性,若存在@Autowired注解,通过Field类设置属性可访问(setAccessible(true))。
- 自动注入依赖的 Bean 实例,实现 “控制反转”。
总结反射是 Java 动态编程的核心技术,通过操作Class、Constructor、Field和Method等类,可在运行时灵活操作类的成员。尽管反射会牺牲部分性能并打破封装性,但在框架开发(如 Spring、MyBatis)中不可或缺。掌握反射,能更深入理解 Java 的底层机制和框架原理。 查看详情:https://www.toutiao.com/article/7538787527894549001 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |