Java反射

今天在程序中用到java反射机制时,遇到的问题记录一下:我当时遇到的问题是,我用反射getMethod()调用类方法时,发生 NoSuchMethodException异常,后来上网发现getMethod()调用公共方法,不能反射调用私有方法,后来找到 getDeclaredField()能够访问本类中定义的所有方法。后来用这个方法解决了我遇到的问题。我查了java api文档,其中详细说明如下:

Method getDeclaredMethod(String name, Class… parameterTypes)d

          返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

Method[] getDeclaredMethods()

          返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

Method getMethod(String name, Class… parameterTypes)

          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

Method[] getMethods()

          返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

getDeclaredField(String name)

          返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

Field[] getDeclaredFields()

          返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。

 

关于invoke的说明:

 

Class类获取Method

getMethod

 

public Method getMethod(String name,

                        Class<?>... parameterTypes)

                 throws NoSuchMethodException,

                        SecurityException

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

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

在 C 中搜索任一匹配的方法。如果找不到匹配的方法,则将在 C 的超类上递归调用第 1 步算法。

如果在第 1 步中没有找到任何方法,则在 C 的超接口中搜索匹配的方法。如果找到了这样的方法,则反映该方法。

在 C 类中查找匹配的方法:如果 C 正好声明了一个具有指定名称的公共方法并且恰恰有相同的形参类型,则它就是反映的方法。如果在 C 中找到了多个这样的方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则反映该方法;否则将从中任选一个方法。

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

getDeclaredMethods

 

public Method[] getDeclaredMethods()

                            throws SecurityException

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何方法,或者此 Class 对象 表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。类初始化方法 <clinit> 不包含在返回数组中。如果该类声明带有相同参数类型的多个公共成员方法,则它们都包含在返回的数组中。

请参阅 Java Language Specification 第 8.2 节。

返回:

表示此类所有声明方法的 Method 对象的数组

抛出:

SecurityException - 如果存在安全管理器 s,并满足下列任一条件:

调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问该类中已声明的方法

调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包

public class InvokeTester {

 private String name;

 private int add(int a,int b)

 {

  return a+b;

 }   

}

获取Method的方法:

 Object obj=InvokeTester.class.newInstance();

 Method addMethod= invokeTesterClass.getDeclaredMethod("add", new Class[]{int.class,int.class} );

试用invoke调用add方法:

Object result= addMethod.invoke(obj, new Object[]{new Integer(100),new Integer(100)});

注意:invoke的第一个参数为对应方法类的instance实例,第二个参数为object数组,每一项是方法的形式参数。

 

posted @ 2014-08-04 17:38  黎明露珠  阅读(196)  评论(0编辑  收藏  举报