反射的回顾 📅 2026/8/5 21:17:05 什么是反射JAVA反射机制是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意一个方法和属性这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制获取Class实例的三种方式Classclazz1String.Class;Classclazz2person.getClass();l/sout(person);L/xxx.yyy.zzz.Person...Classclazz3Class.forName(StringclassPath);//体现反射的动态性反射的常见应用场景反射在Java开发中有着广泛的应用以下是几个典型的实际应用场景框架与库的底层支持Spring框架通过反射实现依赖注入DI和控制反转IoC动态创建和管理Bean实例。JUnit测试框架利用反射自动发现并执行带有Test注解的测试方法。序列化与反序列化JSON/XML序列化库如Jackson、Gson通过反射读取对象的字段信息将其转换为JSON/XML格式或从JSON/XML重建对象。Java原生序列化Serializable接口的底层实现依赖反射来访问对象的私有字段。动态代理与AOPJava动态代理Proxy.newProxyInstance()在运行时创建接口的代理实例拦截方法调用并执行额外逻辑如日志、事务。Spring AOP基于动态代理和反射实现面向切面编程在不修改源代码的情况下增强方法功能。注解处理器编译时注解处理如Lombok通过反射分析带有注解的类在编译期生成额外的代码如getter/setter、Builder模式。运行时注解解析如Spring的Autowired、RequestMapping框架在启动时扫描类路径通过反射读取注解信息并完成相应的配置和绑定。工具类与通用代码对象拷贝工具如BeanUtils.copyProperties通过反射读取源对象的属性值并设置到目标对象的对应属性中。数据库ORM映射如早期Hibernate、MyBatis部分功能将数据库查询结果集的列通过反射映射到Java对象的字段上。这些场景体现了反射的核心价值在运行时动态地操作类、对象和方法为框架、工具和通用逻辑提供灵活性和扩展性。当然反射也会带来性能开销和安全隐患因此在实际使用中需要权衡利弊。Java反射代码示例下面是一个完整的Java代码示例展示如何通过反射获取类名、方法和属性并调用方法包含必要的异常处理importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;publicclassReflectionExample{// 定义一个简单的Person类用于演示staticclassPerson{privateStringname;privateintage;publicPerson(){this.name张三;this.age25;}publicPerson(Stringname,intage){this.namename;this.ageage;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.ageage;}publicvoidintroduce(){System.out.println(大家好我是name今年age岁。);}privatevoidprivateMethod(){System.out.println(这是一个私有方法);}}publicstaticvoidmain(String[]args){try{// 1. 获取Class实例// 关键步骤1使用Class.forName()动态加载类这是反射的起点// 注意参数必须是类的全限定名包含包名内部类用$分隔// 可能抛出ClassNotFoundException需要捕获处理Class?clazzClass.forName(ReflectionExample$Person);System.out.println(1. 获取Class实例: clazz.getName());System.out.println( 简单类名: clazz.getSimpleName());System.out.println();// 2. 创建对象实例// 关键步骤2通过无参构造器创建对象实例// getDeclaredConstructor()获取声明的构造器newInstance()创建实例// 可能抛出InstantiationException、IllegalAccessException等异常ObjectpersonInstanceclazz.getDeclaredConstructor().newInstance();System.out.println(2. 创建对象实例成功);System.out.println();// 3. 获取所有公共方法System.out.println(3. 获取所有公共方法:);// getMethods()返回所有公共方法包括从父类继承的方法// 注意这可能会返回大量方法如Object类的方法Method[]methodsclazz.getMethods();for(Methodmethod:methods){System.out.println( - Modifier.toString(method.getModifiers()) method.getReturnType().getSimpleName() method.getName()());}System.out.println();// 4. 获取所有声明的方法包括私有方法System.out.println(4. 获取所有声明的方法包括私有:);// getDeclaredMethods()返回本类声明的所有方法包括私有、受保护、包访问和公共方法// 注意不包括继承的方法只包含当前类直接声明的方法Method[]declaredMethodsclazz.getDeclaredMethods();for(Methodmethod:declaredMethods){System.out.println( - Modifier.toString(method.getModifiers()) method.getReturnType().getSimpleName() method.getName()());}System.out.println();// 5. 获取所有属性System.out.println(5. 获取所有属性:);// getDeclaredFields()返回本类声明的所有字段包括私有字段// 注意不包括继承的字段只包含当前类直接声明的字段Field[]fieldsclazz.getDeclaredFields();for(Fieldfield:fields){System.out.println( - Modifier.toString(field.getModifiers()) field.getType().getSimpleName() field.getName());}System.out.println();// 6. 调用公共方法System.out.println(6. 调用公共方法:);// 关键步骤3获取指定名称的公共方法// getMethod()只能获取公共方法需要精确匹配方法名和参数类型// 可能抛出NoSuchMethodExceptionMethodgetNameMethodclazz.getMethod(getName);// invoke()动态调用方法第一个参数是调用对象后续是方法参数// 注意返回值是Object类型需要强制类型转换Stringname(String)getNameMethod.invoke(personInstance);System.out.println( 调用getName()方法结果: name);MethodintroduceMethodclazz.getMethod(introduce);System.out.print( 调用introduce()方法结果: );introduceMethod.invoke(personInstance);System.out.println();// 7. 访问和修改私有属性System.out.println(7. 访问和修改私有属性:);// 关键步骤4获取私有字段// getDeclaredField()可以获取任何访问权限的字段包括私有字段FieldnameFieldclazz.getDeclaredField(name);// 关键步骤5突破访问限制// setAccessible(true)是访问私有成员的关键它会取消Java语言访问检查// 注意这会破坏封装性应谨慎使用且可能受到安全管理器限制nameField.setAccessible(true);// 设置可访问私有属性// 获取字段值需要传入对象实例StringcurrentName(String)nameField.get(personInstance);System.out.println( 当前name属性值: currentName);// 修改字段值需要传入对象实例和新值// 注意直接修改私有字段可能破坏对象的不变性约束nameField.set(personInstance,李四);System.out.println( 修改后name属性值: ((Person)personInstance).getName());System.out.println();// 8. 调用私有方法System.out.println(8. 调用私有方法:);// 关键步骤6获取私有方法// getDeclaredMethod()可以获取任何访问权限的方法包括私有方法MethodprivateMethodclazz.getDeclaredMethod(privateMethod);// 同样需要setAccessible(true)来突破访问限制// 注意调用私有方法可能破坏类的封装设计应仅在特殊场景下使用privateMethod.setAccessible(true);// 设置可访问私有方法System.out.print( 调用privateMethod()结果: );privateMethod.invoke(personInstance);}catch(ClassNotFoundExceptione){System.err.println(类未找到: e.getMessage());}catch(NoSuchMethodExceptione){System.err.println(方法未找到: e.getMessage());}catch(IllegalAccessExceptione){System.err.println(非法访问: e.getMessage());}catch(InstantiationExceptione){System.err.println(实例化异常: e.getMessage());}catch(Exceptione){System.err.println(其他异常: e.getClass().getName() - e.getMessage());e.printStackTrace();}}}代码说明获取Class实例使用Class.forName()动态加载类这是反射的起点创建实例通过getDeclaredConstructor().newInstance()创建对象获取方法getMethods()获取所有公共方法包括继承的getDeclaredMethods()获取本类声明的所有方法包括私有获取属性getDeclaredFields()获取本类声明的所有属性调用方法Method.invoke()动态调用方法访问私有成员通过setAccessible(true)突破访问限制异常处理使用try-catch捕获反射可能抛出的各种异常运行结果示例1. 获取Class实例: ReflectionExample$Person 简单类名: Person 2. 创建对象实例成功 3. 获取所有公共方法: - public String getName() - public void setName(String) - public int getAge() - public void setAge(int) - public void introduce() - public final void wait() - public final void wait(long,int) - public final native void wait(long) - public boolean equals(Object) - public String toString() - public native int hashCode() - public final native Class getClass() - public final native void notify() - public final native void notifyAll() 4. 获取所有声明的方法包括私有: - public String getName() - public void setName(String) - public int getAge() - public void setAge(int) - public void introduce() - private void privateMethod() 5. 获取所有属性: - private String name - private int age 6. 调用公共方法: 调用getName()方法结果: 张三 调用introduce()方法结果: 大家好我是张三今年25岁。 7. 访问和修改私有属性: 当前name属性值: 张三 修改后name属性值: 李四 8. 调用私有方法: 调用privateMethod()结果: 这是一个私有方法这个示例完整展示了Java反射的核心功能包括获取类信息、方法、属性以及动态调用和修改同时包含了全面的异常处理机制。