通过反射获取及调用方法(Method)

您所在的位置:网站首页 getdeclaredmethod参数类型 通过反射获取及调用方法(Method)

通过反射获取及调用方法(Method)

2024-01-06 17:09| 来源: 网络整理| 查看: 265

本篇文章包含3个方面分别是: 1、获取方法 使用反射获取某一个类中的方法,步骤: ①找到获取方法所在类的字节码对象 ②找到需要被获取的方法

Class类中常用方法: public Method[] getMethods():获取包括自身和继承过来的所有的public方法

public Method[] getDeclaredMethods():获取自身所有的方法(不包括继承的,和访问权限无关)

public Method getMethod(String methodName,Class...parameterTypes):

表示调用指定的一个公共的方法(包括继承的)

参数:

methodName: 表示被调用方法的名字

parameterTypes:表示被调用方法的参数的Class类型如String.class

只有通过方法签名才能找到唯一的方法,方法签名=方法名+参数列表(参数类型、参数个数、参数顺序)。

public Method getDeclaredMethod(String name,

Class... parameterTypes):表示调用指定的一个本类中的方法(不包括继承的) 参数: methodName: 表示被调用方法的名字 parameterTypes:表示被调用方法的参数的Class类型如String.class

总结: 四个方法中,不带Declared的方法能获取自身类和父类的所有public方法。带Declared的方法能获取自身所有方法但不能获取父类中的方法。 只有通过方法签名才能找到唯一的方法,方法签名=方法名+参数列表(参数类型、参数个数、参数顺序)。 只能获取父类中的public方法,无法获取到父类的默认权限和private权限方法。 测试代码如下: class P{

public void t1(){} void t2(){} private void t3(){}

}

class People extends P{

public void sayHi() { System.out.println("sayHi()"); } public void sayHello(String name) { System.out.println("sayHello(String name) " + "name = " + name); } private void sayGoodBye(String name, int age) { System.out.println("sayGoodBye(String name, int age) " + "name = " + name + " age = " + age); }

}

public class MethodDemo {

public static void main(String[] args) throws Exception { Class clazz = People.class; //获取类自身及父类所有public方法 Method ms[] = clazz.getMethods(); for (Method m : ms) { System.out.println(m); } System.out.println("---------------------------"); //获取类自身所有方法(不会获取父类方法) ms = clazz.getDeclaredMethods(); for (Method m : ms) { System.out.println(m); } System.out.println("---------------------------"); //只能获取父类中的public方法,无法获取到父类的默认权限和private权限方法 Method m = clazz.getMethod("t1", null);//public void com.reflex.P.t1() System.out.println(m);

// m = clazz.getMethod("t2", null);//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.t2()

// m = clazz.getMethod("t3", null);//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.t3()

m = clazz.getMethod("sayHello", String.class); System.out.println(m); //Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.sayGoodBye(java.lang.String, int) //getMethod方法只能获取public的

// m = clazz.getMethod("sayGoodBye", String.class,int.class);

// System.out.println(m);

m = clazz.getDeclaredMethod("sayGoodBye", String.class,int.class); System.out.println(m); //带Declared的无法获取父类中的方法

// m = clazz.getDeclaredMethod("t1", null);//Exception in thread "main" java.lang.NoSuchMethodException: com.reflex.People.t1()

// System.out.println(m);

}

}

2、调用方法 使用反射调用方法步骤: ①找到被调用方法所在的字节码 ②获取到被调用的方法对象 ③调用该方法

如何使用反射调用一个方法: 在Method类中有方法: public Object invoke(Object obj,Object... args):表示调用当前Method所表示的方法

参数: obj: 表示被调用方法底层所属对象 Method m = clz.getMethod("sayHi",String.class); args:表示调用方法是传递的实际参数 返回: 底层方法的返回结果

obj: 表示被调用方法底层所属对象举例说明如下: class Test {

public String sayHi(String name) { System.out.println("sayHi()......." + name); return "XXX"; }

}

sayHi的底层所属对象就是Test的对象:以前调用方法:

Test e = new Test(); String ret = e.sayHi("huangweiyong");

调用私有方法(切记): 在调用私有方法之前:应该设置该方法为可访问的 又因为Method是AccessibleObject子类,所以Method中具有该方法. sayGoodByeMethod.setAccessible(true);

3、调用静态方法和可变参数方法 使用反射调用静态方法: public Object invoke(Object obj,Object... args); 如果底层方法是静态的,那么可以忽略指定的 obj参数。将obj参数设置为null即可。

使用反射调用可变参数的方法: 对于数组类型的引用类型的参数,底层会自动解包,为了解决该问题,我们使用Object的一维数组把实际参数包装起来.

(牢记)以后使用反射调用invoke方法,在传递实际参数的时候,无论是基本数据类型还是引用数据类型,也无论是可变参数类型,反正就是一切实际参数都包装在newObject[]{}中,就没问题。

m.invoke(方法底层所属对象,newObject[]{实际参数});通用

下面写个例子加强理解: public class VarArgsMethodDemo {

public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.reflex.VarArgsMethodDemo"); Method m = clazz.getMethod("sum", int[].class);

// m.invoke(null, 1,2,3,4);//error

m.invoke(null, new int[]{1,2,3});//yes m.invoke(null, new Object[]{new int[]{1,3,4}});//yes System.out.println("---------------------------"); m = clazz.getMethod("toStr", String[].class);

// m.invoke(null, "A","q","cc");//error

// m.invoke(null, new String[]{"A","q","cc"});//error 引用类型和基本数据类型的区别,基本数据类型可以直接使用,这里会自动解包,我们需要手动包装一层

// 对于数组类型的引用类型的参数,底层会自动解包,为了解决该问题,我们使用Object的一维数组把实际参数包装起来.

//new Object[]{new String[]{"huang ","weiyong"," 18"}} 解包成new String[]{"huang ","weiyong"," 18"} m.invoke(null, new Object[]{new String[]{"huang ","weiyong"," 18"}}); } //可变参数底层就是数组 //基本数据类型 public static int sum(int ...args) { int sum = 0; for (int i : args) { sum+=i; } System.out.println(sum); return sum; } //引用数据类型 public static void toStr(String ...args) { System.out.println(Arrays.toString(args)); }

}



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3