Java通过反射执行方法(获取方法)

要动态获取一个对象方法的信息,首先需要通过下列方法之一创建一个Method类型的对象或者数组。

getMethods()

getMethods(Stringname,Class<?>…parameterTypes)

getDeclaredMethods()

getDeclaredMethods(Stringname,Class<?>...parameterTypes)

如果是访问指定的构造方法,需要根据该方法的入口参数的类型来访问。例如,访问一个名称为max,入口参数类型依次为int和String类型的方法。

下面的两种方式均可以实现:

objectClass.getDeclaredConstructor("max",int.class,String.class);
objectClass.getDeclaredConstructor("max",new Class[]{int.class,String.class});12复制代码类型:[java]

Method类的常用方法如表3所示。

表1Method类的常用方法

静态方法名称 说明
getName() 获取该方法的名称
getParameterType() 按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType() 以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes() 以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object...args) 利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs() 查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回 false
getModifiers() 获得可以解析出该方法所采用修饰符的整数

例2

下面通过一个案例来演示如何调用Method类的方法获取动态类中方法的信息。

1)首先创建一个Book1类,并编写4个具有不同作用域的方法。Book1类的最终代码如下:

public class Book1 { // static 作用域方法
 static void staticMethod() {
  System.out.println("执行staticMethod()方法");
 } // public 作用域方法
 public int publicMethod(int i) {
  System.out.println("执行publicMethod()方法");  return 100 + i;
 } // protected 作用域方法
 protected int protectedMethod(String s, int i) throws NumberFormatException {
  System.out.println("执行protectedMethod()方法");  return Integer.valueOf(s) + i;
 } // private 作用域方法
 private String privateMethod(String... strings) {
  System.out.println("执行privateMethod()方法");
  StringBuffer sb = new StringBuffer();  for (int i = 0; i < sb.length(); i++) {
   sb.append(strings[i]);
  }  return sb.toString();
 }
}1234567891011121314151617181920212223242526复制代码类型:[java]

2)编写测试类Test02,在该类的main()方法中通过反射访问Book1类中的所有方法,并将该方法是否带可变类型参数、入口参数类型和可能拋出的异常类型信息输出到控制台。

Test02类的代码如下:

public class Test02 { public static void main(String[] args) {  // 获取动态类Book1
  Book1 book = new Book1();
  Class class1 = book.getClass();  // 获取Book1类的所有方法
  Method[] declaredMethods = class1.getDeclaredMethods();  for (int i = 0; i < declaredMethods.length; i++) {
   Method method = declaredMethods[i];
   System.out.println("方法名称为:" + method.getName());
   System.out.println("方法是否带有可变数量的参数:" + method.isVarArgs());
   System.out.println("方法的参数类型依次为:");   // 获取所有参数类型
   Class[] methodType = method.getParameterTypes();   for (int j = 0; j < methodType.length; j++) {
 System.out.println(" " + methodType[j]);
   }   // 获取返回值类型
   System.out.println("方法的返回值类型为:" + method.getReturnType());
   System.out.println("方法可能抛出的异常类型有:");   // 获取所有可能抛出的异常
   Class[] methodExceptions = method.getExceptionTypes();   for (int j = 0; j < methodExceptions.length; j++) {
 System.out.println(" " + methodExceptions[j]);
   }   boolean isTurn = true;   while (isTurn) { try { // 如果该成员变量的访问权限为private,则抛出异常
  isTurn = false;  if (method.getName().equals("staticMethod")) { // 调用没有参数的方法
   method.invoke(book);
  } else if (method.getName().equals("publicMethod")) { // 调用一个参数的方法
   System.out.println("publicMethod(10)的返回值为:" + method.invoke(book, 10));
  } else if (method.getName().equals("protectedMethod")) { // 调用两个参数的方法
   System.out.println("protectedMethod(\"10\",15)的返回值为:" + method.invoke(book, "10", 15));
  } else if (method.getName().equals("privateMethod")) { // 调用可变数量参数的方法
   Object[] parameters = new Object[] { new String[] { "J", "A", "V", "A" } };
   System.out.println("privateMethod()的返回值为:" + method.invoke(book, parameters));
  }
 } catch (Exception e) {
  System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法");
  method.setAccessible(true); // 设置为允许访问private方法
  isTurn = true;
 }
   }
   System.out.println("=============================\n");
  }
 }
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950复制代码类型:[java]

3)运行测试类test02,程序将会依次动态访问Book1类中的所有方法。访问staticMethod()方法的运行效果如下所示:

方法名称为:staticMethod
方法是否带有可变数量的参数:false方法的参数类型依次为:
方法的返回值类型为:void方法可能抛出的异常类型有:
执行staticMethod()方法
=============================1234567复制代码类型:[java]

访问publicMethod()方法的运行效果如下所示:

方法名称为:publicMethod
方法是否带有可变数量的参数:false方法的参数类型依次为:int方法的返回值类型为:int方法可能抛出的异常类型有:
执行publicMethod()方法
publicMethod(10)的返回值为:110=============================123456789复制代码类型:[java]

访问protectedMethod()方法的运行效果如下所示:

方法名称为:protectedMethod
方法是否带有可变数量的参数:false方法的参数类型依次为:class java.lang.Stringint方法的返回值类型为:int方法可能抛出的异常类型有:class java.lang.NumberFormatException执行protectedMethod()方法protectedMethod("10",15)的返回值为:25=============================1234567891011复制代码类型:[java]

访问privateMethod()方法的运行效果如下所示:

方法名称为:privateMethod
方法是否带有可变数量的参数:true方法的参数类型依次为:class java.lang.String;
方法的返回值类型为:class java.lang.String方法可能抛出的异常类型有:
在设置成员变量值时抛出异常,下面执行setAccessible()方法
执行privateMethod()方法privateMethod()的返回值为:=============================
(0)

相关推荐

  • Java反射

    一.概念 运行状态中知道类所有的属性和方法. 在Java中的反射机制是指在运行状态中,对于任意一个类都能知道这个类的所有属性和方法,并且对于任意一个对象,都能调用它的任意一个方法.这种能够获取信息以及 ...

  • 小技巧丨两种方法获取任意地区CAD地形图!

    Ladies & 乡亲们!钱哥的小技巧第二讲终于跟大家见面啦! 通过上次钱哥对map stack的介绍(又一款地图制作神器 Map Stack),很多小伙伴对前期地图制作的速度有一个质的飞跃, ...

  • Java中String类的concat方法

    在了解concat()之前,首先需要明确的是String的两点特殊性. 长度不可变 值不可变  这两点从源码中对String的声明可以体现: private final char[] value ; ...

  • 地面控制点GCP的获取方法

    地形图 其他参考DEM数据集 手持GPS RTK Lidar

  • 苹果系统也能用管控孩子玩手机的APP,附获取方法

    有一项历时为10年的研究报告是这样的:研究跟踪100名孩子,其中50名是手机依赖者,另外50名是接触不到手机的孩子.最后的调查结果显示:50名手机依赖者中只有两名孩子考上了大学,而没有接触到手机的孩子 ...

  • 王者荣耀:是bug还是福利?天美泄露新英雄获取方法,这下尴尬了

    曼姐出品,必属优品.大家好,我是人见人爱的小曼姐.大家都知道,自从前段时间天美更新版本之后,就有很多新活动上线.同时,新英雄和新皮肤也是大家一直关注的对象.以前的王者荣耀一个赛季也就只出3个新英雄和3 ...

  • Java创建线程的两个方法

    Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...

  • selenium+python自动化101-execute_script 方法获取 JavaScript 返回值

    前言 之前经常使用 execute_script() 方法执行 JavaScript 的来解决页面上一些 selenium 无法操作的元素,但是一直无法获取执行的返回值. 最近翻文档,发现 execu ...

  • Android 手机app三种方法获取定位地址(自带API,外接SDK,获取外网IP)

    一.手机App定位在我看来有三种方法: 1.通过Android自带的API:LocationManager获取到经纬度,再通过Geocoder反地理位置查询到所在的地址. 2.外接SDK,如高德SDK ...

  • 最新中国电信光猫超级密码获取方法

    现在家里的华为等品牌的光猫都带有路由功能,对于不少人来说这个路由功能太少,像MAC绑定.WIFI功率.黑名单.防火墙等都无法自定义,对于网络要求高的人来说这个性能不足的路由更会影响网络性能.只想要光猫 ...