bingoideas

轻叩枝头结,默数桃花开
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

java反射示例

Posted on 2011-03-29 16:51  bingoideas  阅读(737)  评论(0编辑  收藏  举报

被测试类

TestMethod.java

 

package cn.reflect;

public class TestMethod {
 public void test() {
  System.out.println("---------");
 }

 public String meth() {
  return "hello";
 }

 public static String meo() {
  return "wsm";
 }
 public String tests(String s){
  System.out.println("++++++++++");
  return s;
 }
}

 

测试类

package cn.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestReflection {
 public static void main(String[] args) throws ClassNotFoundException,
   SecurityException, NoSuchMethodException, IllegalArgumentException,
   IllegalAccessException, InvocationTargetException, InstantiationException {
  ClassLoader cl = Thread.currentThread().getContextClassLoader();
  Class c = null;
  c = cl.loadClass("cn.reflect.TestMethod");
  Method[] m = c.getMethods();
  //第一个参数是方法名 第二个参数是tests方法形式参数的类型,对于多个形式参数,会有多个类型,他们共同组成一个Class[]数组,对于tests方法,只有一个参数
  Method method = c.getMethod("tests", new Class[]{String.class});
//  for (int i = 0; i < m.length; i++) {
//   // 输出方法的返回类型
//   System.out.print(m[i].getReturnType().getName());
//   // 输出方法名
//   System.out.print(" " + m[i].getName() + "(");
//   // 获取方法的参数
//   Class[] parameterTypes = m[i].getParameterTypes();
//   for (int j = 0; j < parameterTypes.length; j++) {
//    System.out.print(parameterTypes[j].getName());
//    if (parameterTypes.length > j + 1) {
//     System.out.print(",");
//    }
//   }
//   
//   System.out.println(")");
//  }
  Object o = null;
  //第一个参数是TestMethod类的实例对象 第二个参数是tests方法的参数,参数可能有多个,他们共同组成一个Object数组
  o = method.invoke(c.newInstance(), new Object[] {new String("asjdflkajglkjadsflk")});
  System.out.println(o);
 }
}

 

另:附Class.getMethod方法说明

 

getMethod

public Method getMethod(String name,
                        Class<?>... parameterTypes)
                 throws NoSuchMethodException,
                        SecurityException
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypesnull,则按空数组处理。

如果 name 是 "<init>;" 或 "<clinit>",则将引发 NoSuchMethodException。否则,要反映的方法由下面的算法确定(设 C 为此对象所表示的类):

  1. 在 C 中搜索任一匹配的方法。如果找不到匹配的方法,则将在 C 的超类上递归调用第 1 步算法。
  2. 如果在第 1 步中没有找到任何方法,则在 C 的超接口中搜索匹配的方法。如果找到了这样的方法,则反映该方法。
在 C 类中查找匹配的方法:如果 C 正好声明了一个具有指定名称的公共方法并且恰恰有相同的形参类型,则它就是反映的方法。如果在 C 中找到了多个这样的方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则反映该方法;否则将从中任选一个方法。

注意,类中可以有多个匹配方法,因为尽管 Java 语言禁止类声明带有相同签名但不同返回类型的多个方法,但 Java 虚拟机并不禁止。这增加了虚拟机的灵活性,可以用来实现各种语言特性。例如,可以使用桥方法 (brige method)实现协变返回;桥方法以及将被重写的方法将具有相同的签名,不同的返回类型。

请参阅Java 语言规范 第 8.2 和 8.4 节。

 

参数:
name - 方法名
parameterTypes - 参数列表
返回:
与指定的 nameparameterTypes 匹配的 Method 对象
抛出:
NoSuchMethodException - 如果找不到匹配的方法,或者方法名为 "<init>" 或 "<clinit>"
NullPointerException - 如果 namenull
SecurityException - 如果存在安全管理器 s,并满足下列任一条件:
从以下版本开始:
JDK1.1

还有Method.invoke方法说明

 

invoke

public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。

如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。

如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。

 

参数:
obj - 从中调用底层方法的对象
args - 用于方法调用的参数
返回:
使用参数 argsobj 上指派该对象所表示方法的结果
抛出:
IllegalAccessException - 如果此 Method 对象强制执行 Java 语言访问控制,并且底层方法是不可访问的。
IllegalArgumentException - 如果该方法是实例方法,且指定对象参数不是声明底层方法的类或接口(或其中的子类或实现程序)的实例;如果实参和形参的数量不相同;如果基本参数的解包转换失败;如果在解包后,无法通过方法调用转换将参数值转换为相应的形参类型。
InvocationTargetException - 如果底层方法抛出异常。
NullPointerException - 如果指定对象为 null,且该方法是一个实例方法。
ExceptionInInitializerError - 如果由此方法引起的初始化失败。