(3)反射调用普通方法
在Class类中有如 下两种取得类中普通方法的函数:
A. 取得所有的普通方法:
public Method[] getMethods():获得所有的public修饰的方法(包含父列的方法也包含Object类)
public Method[] getDeclaredMethods():获得所有成员方法,包括私有的但不包括继承的。
B. 取得指定参数的普通方法:
public Method getMethod(String name,Class<?>... parameterTypes):
获得指定参数的权限为public的普通方法,
public Method getDeclaredMethod(String name,Class<?>... parameterTypes):
获得指定参数的成员方法,权限任意,且只能是本类中的方法。
C. 调用方法:
Method->public Object invoke(Object obj,Object……args):
obj:要调用的方法对象;args:调用方法时所传递的实参。
//反射调用普通方法 class Person1{ public void demon1() {} protected void demon2() {} private void demon3(String str) {} } class Person extends Person1{ private String name; int age; //无参构造方法 public Person() {} public void print1() { System.out.println("我是公有的普通方法1"); } public void print2(int age) { System.out.println("我是带有参数的公有的普通方法2"+age); } protected void print3() { System.out.println("我是受保护、无参的普通方法3"); } private String print4(String name) { System.out.println("我是带有参数的私有的普通方法4"); return name; } void print() { System.out.println("我是默认的普通方法5"); } } public class Test1{ public static void main(String[] args) throws ClassNotFoundException { Class<?> class1 = Class.forName("reflect.Person"); System.out.println("*************获得访问权限为public的所有普通方法(包括父类、Object类)*********"); //获取所有访问权限为public的普通方法(包括父列和Object类) Method[] methods = class1.getMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("***************获得任意访问权限的所有普通方法(仅本类)**************"); //获取本类中任意访问权限的所有普通方法 Method[] methods2 = class1.getDeclaredMethods(); for (Method method : methods2) { System.out.println(method); } System.out.println("***************获得public访问权限的普通方法(包括父类、Object类)**************"); try { //获取访问权限为public的指定方法(包含父类和Object类) Method method = class1.getMethod("print2", int.class); System.out.println(method); } catch (NoSuchMethodException | SecurityException e) { e.printStackTrace(); } System.out.println("***************获得任意访问权限的普通方法(仅本类)**************"); try { //获取本类中任意访问权限的指定方法 Method method1 = class1.getDeclaredMethod("print4", String.class); System.out.println(method1); //实例化对象 Object obj = class1.getConstructor().newInstance(); //解除私有限定 method1.setAccessible(true); //调用方法,需要两个参数,一个是要调用的对象(获取有反射),一个是实参 System.out.println("******************方法的调用***********************"); Object result = method1.invoke(obj,"lemon"); System.out.println(result); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { e.printStackTrace(); }
(4)反射调用类中属性
在之前已经成功的实现了类的构造调用、方法调用,除了这两种模式之外还有类中属性调用。
前提:类中的所有属性一定在类对象实例化之后才会进行空间分配,所以此时如果要想调用类的属性,必须保证有实例化对象。通过反射的newInstance()可以直接取得实例化对象(Object类型)。
在Class类中提供有两组取得属性的方法:
A. public Field[] getFields():获取类中访问权限为public的所有属性。
public Field[] getDeclaredFields():获取所有属性,包括:私有、受保护、默认、公有;
B. public Field getField(String fieldName):获取指定权限为public的共有指定 属性
public Field getDeclaredField(String fieldName):获取任意权限的指定属性
//反射调用类中属性 class Person{ public String name; int age; private String work; } class Student extends Person{ private String classes; protected char gender; public long ID; } public class Test1{ public static void main(String[] args) throws Exception { Class<?> class1 = Class.forName("reflect.Student"); //获取访问权限为public的所有属性(包含父类) Field[] fields = class1.getFields(); System.out.println("***************获得权限为public的所有属性(包含父类)************************"); for (Field field : fields) { System.out.println(field); } //获取访问权限任意的所有属性 Field[] fields2 = class1.getDeclaredFields(); System.out.println("***************获得本类中权限任意的所有属性************************"); for (Field field : fields2) { System.out.println(field); } //获取访问权限为public的指定属性 Field field = class1.getField("name"); System.out.println("***************获得权限位public的的指定属性(包含父类)************************"); System.out.println(field); //获取访问权限任意的本类中的指定属性 Field field2 = class1.getDeclaredField("classes"); System.out.println("***************获得本类中权限任意的指定属性************************"); System.out.println(field2); } }
C. 通过反射操作属性
通过反射机制我们可以利用set、get来动态的操作属性的值,若需要对private私有属性进行操纵时,则要用到AccessibleObject类中提供有一个方法:
public void setAccessible(boolean flag):动态设置封装性只此一次(指的是在当前的JVM中)。
Field类中还有一个重要方法:
public Class<?> getType():可以取得属性类型
package reflect; import java.io.ObjectInputStream.GetField; import java.lang.reflect.Field; class Person1{ private String name; } public class Test2 { public static void main(String[] args) throws Exception { Class<?> class1 = Class.forName("reflect.Person1"); //实例化本类对象 Object object = class1.newInstance(); System.out.println(object); //操作name属性 Field field = class1.getDeclaredField("name"); //取消封装 field.setAccessible(true); //设置属性 相当于 对象.name = "lemon" field.set(object, "lemon"); //取得属性 System.out.println(field.get(object)); //获取属性的类型(返回值:包名.类名) System.out.println(field.getType()); //获取属性的类型(只返回类名) System.out.println(field.getType().getSimpleName()); } }