java反射——实现程序的动态性

    xiaoxiao2022-06-29  30

    转自http://uuhorse.iteye.com/blog/1706466

    ① 创建对象     如果知道一个类型,很容易使用new操作符创建一个类的实例。但是如果在编译时并不知道具体要实例化的是哪个类的对象,如何创建该实例呢?     Java中提供Class.forName(String className)从一个字符串(含包的类全名称)加载一个类,再利用newInstance方法创建该类的实例。 

    //动态创建类对象 public static Object createObject(String className) { Object object = null; try { Class classDefinition = Class.forName(className); object = classDefinition.newInstance(); } catch (InstantiationException e) { System.out.println(e); } catch (IllegalAccessException e) { System.out.println(e); } catch (ClassNotFoundException e) { System.out.println(e); } return object; } 当然,也可以先获取一个类的Constructor,再调用其newInstance方法创建对象。不同的是,constructor对象的newInstance方法需要传递一个对象数组作为构造方法的参数列表。

    //使用Constructor动态创建对象 public static Object createObject(Constructor constructor, Object[] arguments) { System.out.println("Constructor: " + constructor.toString()); Object object = null; try { object = constructor.newInstance(arguments); System.out.println("Object: " + object.toString()); return object; } catch (InstantiationException e) { System.out.println(e); } catch (IllegalAccessException e) { System.out.println(e); } catch (IllegalArgumentException e) { System.out.println(e); } catch (InvocationTargetException e) { System.out.println(e); } return object; } ② 获取/设置字段值     利用Reflection API获取或者设置字段的值,首先要得到Class对象,然后利用Class对象的getField方法取得相应的字段Field对象,然后调用Field对象对应的getXXX/setXXX方法获取或者设置属性的值。Filed对象提供getInt/setInt、getLong/setLong等方法对基本类型的属性进行值的获取和设置,可以直接使用get/set方法获取复杂类型属性的值(返回一个对象值/传递一个对象值作为参数)。     具体操作方法见如下代码片段。当然,若试图获取/设置一个非public的字段值(getField方法也不能获取非pubic的属性对象,可以尝试使用getDeclaredField方法),将产生IllegalAccessException,可以通过setAccessible(true)使非public的字段可见,然后对字段值进行访问。

    // 获取字段值 static void getFiledValue(Object o, String filedName) { Class c = o.getClass(); Field filed; Object value; try { filed = c.getField(filedName); // filed = c.getDeclaredField(filedName); // filed.setAccessible(true); //修改字段访问权限 value = filed.get(o); //可使用getInt、getLong等(若知晓字段基本类型) System.out.println(filedName + ": " + value.toString()); } catch (NoSuchFieldException e) { System.out.println(e); } catch (SecurityException e) { System.out.println(e); } catch (IllegalAccessException e) { System.out.println(e); } } // 修改字段值 public static void setFieldValue(Object o, String filedName, Object value) { Field filed; Class c = o.getClass(); try { filed = c.getField(filedName); // filed = c.getDeclaredField(filedName); // filed.setAccessible(true); //修改字段访问权限 filed.set(o, value); //可使用setInt、setLong等(若知晓字段基本类型) } catch (NoSuchFieldException e) { System.out.println(e); } catch (IllegalAccessException e) { System.out.println(e); } } ③ 调用方法     方法调用的过程类似于设置字段值的过程,首先要得到Class对象,然后调用getMethod方法得到方法Method的对象,getMethod方法要求传递两个参数,一个是方法名,第二个是Class[],即方法参数列表中各参数对应的类型的数组。然后执行Method对象的invoke方法,进行方法的调用,invoke方法需要传递两个参数,第一个是方法绑定的对象,第二个是方法的参数列表。如果是static的方法,则第一个参数将自动被忽略(可为null)。     同理,对于非public的方法,可以使用getDeclaredMethod方法获取Method对象,并使用setAccessible设置其可见性。 

    //动态调用方法 public static Object callMethod(Object o, String methodName, Class paramsType[], Object paramsValue[]) { Object result = null; Class c; Method method; try { c = o.getClass(); method = c.getMethod(methodName, paramsType); // method = c.getDeclaredMethod(methodName, paramsType); // method.setAccessible(true); result = method.invoke(o, paramsValue); } catch (NoSuchMethodException e) { System.out.println(e); } catch (IllegalAccessException e) { System.out.println(e); } catch (InvocationTargetException e) { System.out.println(e); } return result; }

    转载请注明原文地址: https://ju.6miu.com/read-1124865.html

    最新回复(0)