怎样用反射对Constructor对象、Field对象、Method对象进行操作

Grizelda ·
更新时间:2024-11-13
· 571 次阅读

1、概念和使用场景 1.1 反射概念

​ 反射是Java中的一种机制,我的编写好的Java文件是不能直接运行,需要编译成class文件,jvm将Class文件加载进内存,并读取Class文件中的内容(该内容就是我们类中写的东西)封装成一个Class对象,并且类的各个组成部分也都被封装成一个个对象。成员变量会被封装成Field对象,构造方法会被封装成Constructor对象,成员方法会被封装成Method对象,这些对象都统一保存在Class对象身上。Java中的反射机制就是要求我们通过Class对象操作Field、Constructor、Method对象完成数据的封装。

1.2 使用场景

反射是框架设计的核心部分。

2、获取Class对象的三种方法及其作用 2.1 三种方式 1 通过类名获取Class对象 Class clazz=类名.class; 2 通过对象获取Class对象 Class clazz=对象.getClass(); 3 通过Class类型的forName()静态方法获取 Class clazz=Class.forName("全类名"); //报名.类名 2.2 代码演示 public class ReflectClass { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { //1 通过类名获取Class对象 Class userClass = User.class; System.out.println(userClass); //2 通过对象获取Class对象 User user=new User(); Class userClass2 = user.getClass(); System.out.println(userClass2); //3 通过Class类型的forName()静态方法获取 Class userClass3 = Class.forName("com.domain.User"); System.out.println(userClass3); //userClass、userClass2、userClass3是否是同一个对象? 是的 System.out.println(userClass==userClass2); System.out.println(userClass==userClass3); //Class对象的作用? //1 可以获取成员变量对象(Field)、获取成员方法对象(Method)、获取构造方法对象(Constructor) //2 可以实例化一个User对象,默认执行的是空参构造 User u = userClass.newInstance(); System.out.println("u = " + u); //3 获取类上的注解参数值 Resource resource = userClass.getAnnotation(Resource.class); String name = resource.name(); System.out.println("name = " + name); } } 3、获取Constructor对象及其作用 3.1 API 1.获取构造方法对象 Constructor[] getConstructors() 获取所有public修饰的构造方法 Constructor getConstructor(Class... parameterTypes) 获取指定参数类型的public修饰的构造方法 Constructor getDeclaredConstructor(Class... parameterTypes) 获取指定参数类型的任意修饰符类型的构造方法 Constructor[] getDeclaredConstructors() 获取任意修饰符类型所有的构造方法 方法规律: 1 方法带Declared表示获取任意修饰符修饰的对象,否则只能获取public修饰的对象 2 方法带s表示获取多个对象,不带s表示获取指定名称的对象 2.实例化对象 Object obj=constructor.newInstance(Object...param);创建对象,并且传递构造需要的参数 3.2 代码演示 package com.itheima_1; import com.domain.User; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /* 1.获取构造方法对象 Constructor[] getConstructors() 获取所有public修饰的构造方法 Constructor getConstructor(Class... parameterTypes) 获取指定参数类型的public修饰的构造方法 Constructor getDeclaredConstructor(Class... parameterTypes) 获取指定参数类型的任意修饰符类型的构造方法 Constructor[] getDeclaredConstructors() 获取任意修饰符类型所有的构造方法 方法规律: 1 方法带Declared表示获取任意修饰符修饰的对象,否则只能获取public修饰的对象 2 方法带s表示获取多个对象,不带s表示获取指定名称的对象 */ public class ReflectConstructor { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //1 获取Class对象 Class userClass = User.class; //2 获取Constructor对象 //Constructor[] getConstructors() 获取所有public修饰的构造方法 // Constructor[] constructors = userClass.getConstructors(); //Constructor[] getDeclaredConstructors() 获取任意修饰符类型所有的构造方法 /*Constructor[] constructors = userClass.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } */ //Constructor getConstructor(Class... parameterTypes) 获取指定参数类型的public修饰的构造方法 // Constructor constructor = userClass.getConstructor(); //Constructor getDeclaredConstructor(Class... parameterTypes) 获取指定参数类型的任意修饰符类型的构造方法 Constructor constructor = userClass.getDeclaredConstructor(); System.out.println(constructor); //3 Constructor的相关操作 //主要就是实例化对象 // User user = constructor.newInstance(); //取消访问权限,又叫暴力访问 constructor.setAccessible(true); User user = constructor.newInstance("java89期 杨焕"); //User user=new User("java89期 杨焕"); System.out.println(user); } }

注意:如果构造是非public修饰的,那么在实例化对象之前调用setAccessible(true);取消访问权限(暴力访问)。

4、获取Field对象及其作用 4.1 API 1.获取成员变量对象 Field[] getFields() :获取所有public修饰的成员变量 Field getField(String name) 获取一个指定名称的public修饰的成员变量 Field[] getDeclaredFields() 获取所有的任意修饰符类型成员变量 Field getDeclaredField(String name) 获取任意修饰符类型指定名称的成员变量 方法规律: 1 方法带Declared表示获取任意修饰符修饰的对象,否则只能获取public修饰的对象 2 方法带s表示获取多个对象,不带s表示获取指定名称的对象 2.赋值和取值 field.get(Object obj);获取哪个对象的field成员变量值; field.set(Object obj, Object value);设置obj对象的field成员变量值为value 4.2 代码演示 public class ReflectField { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException { //1 获取Class对象 Class userClass = User.class; //2 获取Field成员变量对象 //Field[] getFields() :获取所有public修饰的成员变量 //Field[] fields = userClass.getFields(); //Field[] getDeclaredFields() 获取所有的任意修饰符类型成员变量 /*Field[] fields = userClass.getDeclaredFields(); for (Field field : fields) { System.out.println(field); }*/ //Field getField(String name) 获取一个指定名称的public修饰的成员变量 // Field field = userClass.getField("name"); //Field getDeclaredField(String name) 获取任意修饰符类型指定名称的成员变量 Field field = userClass.getDeclaredField("age"); System.out.println(field); //3 操作Field对象 //取消访问权限 field.setAccessible(true); //赋值,field.set(Object obj, Object value);设置obj对象的field成员变量值为value User user = userClass.newInstance(); field.set(user,20); System.out.println(user); //取值,field.get(Object obj);获取哪个对象的field成员变量值; Object age = field.get(user); System.out.println("age = " + age); //其他操作 //获取变量名称 System.out.println(field.getName()); //获取变量类型 System.out.println(field.getGenericType().getTypeName()); //获取修饰符类型 int modifier = field.getModifiers(); System.out.println(Modifier.toString(modifier)); //System.out.println(Modifier.isPrivate(modifier)); } }

注意:如果构造是非public修饰的,那么在调用set()/get()方法之前调用setAccessible(true)取消访问权限(暴力访问)。

5、获取Method对象及其作用 5.1 API 1.获取成员方法对象 Method[] getMethods() 获取所有public修饰的方法(可以获取父类的public修饰的方法) Method getMethod(String name, Class... parameterTypes) 获取一个指定名称指定参数类型的public修饰成员方法 Method[] getDeclaredMethods() 获取任意修饰符类型所有的成员方法 Method getDeclaredMethod(String Class, 类... parameterTypes) 获取一个指定名称指定参数类型的任意修饰符类型成员方法 方法规律: 1 方法带Declared表示获取任意修饰符修饰的对象,否则只能获取public修饰的对象 2 方法带s表示获取多个对象,不带s表示获取指定名称的对象 2.执行方法 method.invoke(Object obj, Object... args);执行obj对象身上的method方法并给方法传递的参数值为args。 5.2 代码演示 public class ReflectMethod { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { //1 获取Class对象 Class userClass = User.class; //2 获取Method对象 //Method[] getMethods() 获取所有public修饰的方法(可以获取父类的public修饰的方法) //Method[] methods = userClass.getMethods(); //Method[] getDeclaredMethods() 获取任意修饰符类型所有的成员方法 /*Method[] methods = userClass.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); }*/ //Method getMethod(String name, Class... parameterTypes) 获取一个指定名称指定参数类型的public修饰成员方法 //Method method = userClass.getMethod("setName", String.class); //Method getDeclaredMethod(String Class, 类... parameterTypes) 获取一个指定名称指定参数类型的任意修饰符类型成员方法 //Method method = userClass.getDeclaredMethod("show1"); Method method = userClass.getDeclaredMethod("show1", String.class); System.out.println(method); //3 操作Method对象 //主要是执行方法 //method.invoke(Object obj, Object... args);执行obj对象身上的method方法并给方法传递的参数值为args。 //暴力访问 method.setAccessible(true); User user = userClass.newInstance(); Object value = method.invoke(user, "吴文波"); System.out.println("value = " + value); //其他使用 //获取方法名 System.out.println(method.getName()); //获取返回值类型 System.out.println(method.getReturnType().getSimpleName()); //返回修饰符类型 System.out.println(Modifier.toString(method.getModifiers())); System.out.println(Modifier.isStatic(method.getModifiers())); //获取参数类型 Class[] parameterTypes = method.getParameterTypes(); for (Class parameterType : parameterTypes) { System.out.println(parameterType.getSimpleName()); } //获取方法上的注解 Resource resource = method.getAnnotation(Resource.class); System.out.println(resource.name()); }

注意:如果构造是非public修饰的,那么在调用invoke()方法之前调用setAccessible(true)取消访问权限(暴力访问)。

6、反射总结

核心:掌握反射操作的基本思路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUJ4iWNd-1587303757539)(img/反射知识点结构图.png)]

7、反射案例 7.1 需求

​ 设计一个BeanUtils工具类,该工具类的作用是将Map集合中的数据封装到对应的JavaBean中。

7.2 代码实现 public class BeanUtils { /** * 将Map集合中的数据封装到对应的bean对象中。 * @param bean 要封装数据的bean对象 * @param map 存储数据的map集合 * 方式1:通过反射Field对象的方式封装 */ /*public static void populate(Object bean, Map map) throws IllegalAccessException { //1 获取Class对象 Class aClass = bean.getClass(); //2 获取所有field对象 Field[] fields = aClass.getDeclaredFields(); //3 遍历所有的Field对象 for (Field field : fields) { //4 遍历map集合,获取所有的key和value Set<Map.Entry> entries = map.entrySet(); for (Map.Entry entry : entries) { String key = entry.getKey(); Object value = entry.getValue(); //5 判断key是否和field名称一致,如果一致就封装数据 if(key.equals(field.getName())){ //取消访问权限 field.setAccessible(true); field.set(bean,value); } } } }*/ /** * 将Map集合中的数据封装到对应的bean对象中。 * @param bean 要封装数据的bean对象 * @param map 存储数据的map集合 * 方式2:通过反射setXxx方法的方式封装 */ /*public static void populate(Object bean, Map map) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { //1 获取Class对象 Class aClass = bean.getClass(); //2 获取所有Method对象 Method[] methods = aClass.getDeclaredMethods(); //3 遍历所有的Method对象 for (Method method : methods) { //4 遍历map集合,获取所有的key和value Set<Map.Entry> entries = map.entrySet(); for (Map.Entry entry : entries) { String key = entry.getKey();//name,age,man,birthday Object value = entry.getValue(); //5 判断"set"+key是否和Method名称一致,如果一致就封装数据 if(method.getName().equalsIgnoreCase("set"+key)){ //执行方法 method.invoke(bean,value); } } } }*/ /** * 将Map集合中的数据封装到对应的bean对象中。 * @param bean 要封装数据的bean对象 * @param map 存储数据的map集合 * 方式3:通过java内省机制的方式封装 */ public static void populate(Object bean, Map map) throws IllegalAccessException, InvocationTargetException, IntrospectionException { //1 获取Class对象 Class aClass = bean.getClass(); //2 遍历map集合,获取所有的key和value Set<Map.Entry> entries = map.entrySet(); for (Map.Entry entry : entries) { String key = entry.getKey(); //name,age,man,birthday Object value = entry.getValue(); //3 根据key创建属性描述器对象,获取setXxx属性方法 PropertyDescriptor pd=new PropertyDescriptor(key,aClass); //获取setXxx属性方法 Method method = pd.getWriteMethod(); //4 执行该方法 method.invoke(bean,value); } } } 8、Java的内省机制

Java的内省机制:Java中提供了一种机制,专门用来获取javabean的属性信息。由三类类操作javabean的属性。

public class IntrospectDemo { public static void main(String[] args) throws IntrospectionException { //获取javabean信息 BeanInfo beanInfo = Introspector.getBeanInfo(User.class); //获取所有的属性方法:setXxx()或者getXxx() PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { //获取setXxx() System.out.println(propertyDescriptor.getWriteMethod()); //获取getXxx() System.out.println(propertyDescriptor.getReadMethod()); } //获取指定名称的setXxx()和getXxx()方法 PropertyDescriptor propertyDescriptor=new PropertyDescriptor("name",User.class); System.out.println(propertyDescriptor.getWriteMethod()); System.out.println(propertyDescriptor.getReadMethod()); } }
作者:Seasonoerror



constructor 反射 method

需要 登录 后方可回复, 如果你还没有账号请 注册新账号