java.lang.reflect包

来源:互联网 发布:linux 服务器增加路由 编辑:程序博客网 时间:2024/04/28 01:40
一.概述
       Reflection API可以使JAVA代码动态的查询和操作正在运行的JAVA类或者接口。Reflection 包含许多的类,例如Method类,该类可以在java.lang.reflect包中找到。

使用Reflection 中的类需要三个步骤:

1.获取一个要操作的类的对象,该对象属于java.lang.object包,该对象代表一个正在运行的一个类或接口。下面的三个方法是常用的获取类对象的方法:

(1) Class c=Class.forname(“java.lang.String”);

使用.forname方法加载一个类,这里是字符串类,从而获得一个与该类对应的类对象。

(2) Class c=int.class;

(3) Class c=Integer.TYPE;

2.获取要操纵的类对象的已经声明的方法

获取类对象的方法的最简单和常用的方法是getDeclareMethods()方法。该方法返回类对象中声明过的所有方法的一个方法数组(Method[])。还有其他的方法,在后面会有所介绍。

3.利用Reflection API操作类。



二.Java.lang.reflect包介绍
java.lang.reflect包中包含有两个接口,八个类。

InvocationHandler接口:

Member接口:该接口可以获取有关类成员(域或者方法)后者构造函数的信息。

AccessibleObject类:该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。

Array类:该类提供动态地生成和访问JAVA数组的方法。

Constructor类:提供一个类的构造函数的信息以及访问类的构造函数的接口。

Field类:提供一个类的域的信息以及访问类的域的接口。

Method类:提供一个类的方法的信息以及访问类的方法的接口。

Modifier类:

Proxy类:提供动态地生成代理类和类实例的静态方法。

ReflectionPermission类:

三.示例与说明
3.1 查找类中声明过的所有方法
import java.lang.reflect.*;



   public class method1 {

      private int f1(

       Object p, int x) throws NullPointerException

      {

         if (p == null)

            throw new NullPointerException();

         return x;

      }

        

      public static void main(String args[])

      {

         try {

           Class cls = Class.forName("method1");

        

            Method methlist[]

              = cls.getDeclaredMethods();

            for (int i = 0; i < methlist.length;

               i++) {  

               Method m = methlist[i];

               System.out.println("name

                 = " + m.getName());

               System.out.println("decl class = " +

                              m.getDeclaringClass());

               Class pvec[] = m.getParameterTypes();

               for (int j = 0; j < pvec.length; j++)

                  System.out.println("

                   param #" + j + " " + pvec[j]);

               Class evec[] = m.getExceptionTypes();

               for (int j = 0; j < evec.length; j++)

                  System.out.println("exc #" + j

                    + " " + evec[j]);

               System.out.println("return type = " +

                                  m.getReturnType());

               System.out.println("-----");

            }

         }

         catch (Throwable e) {

            System.err.println(e);

         }

      }

   }

代码说明:

Class cls = Class.forName("method1");获取一个method1类的类对象cls。

Method methlist[]  = cls.getDeclaredMethods();返回一个类声明的所有方法的方法数组。

m.getDeclaringClass();返回声明该方法的类的实例。返回值为一个class。

m.getName():返回该方法的名字,返回值为字符串类型。

Class pvec[] = m.getParameterTypes():返回该方法的参数的类型的一个数组。注意参数的返回顺序是与方法声明时的顺序是相同的。

Class evec[] = m.getExceptionTypes():获取该方法抛出的例外的一个类型数组。

m.getReturnType():返回该方法的返回值的类型。返回值是一个class。

       除了上述的Method类的方法外,还有别的方法。其中比较重要的有:

Object invoke(Object obj,Object[] args)方法:对该方法进行实际的调用并执行。其中的两个参数的含义分别是调用该方法的一个类实例对象,和调用该方法的参数对象数组。具体如何应用请参看3.4节。



3.2 获取构造函数信息
import java.lang.reflect.*;

        

   public class constructor1 {

      public constructor1()

      {

      }

        

      protected constructor1(int i, double d)

      {

      }

        

      public static void main(String args[])

      {

         try {

           Class cls = Class.forName("constructor1");

        

           Constructor ctorlist[]

               = cls.getDeclaredConstructors();

         for (int i = 0; i < ctorlist.length; i++) {

               Constructor ct = ctorlist[i];

               System.out.println("name

                 = " + ct.getName());

               System.out.println("decl class = " +

                            ct.getDeclaringClass());

               Class pvec[] = ct.getParameterTypes();

               for (int j = 0; j < pvec.length; j++)

                  System.out.println("param #"

                     + j + " " + pvec[j]);

               Class evec[] = ct.getExceptionTypes();

               for (int j = 0; j < evec.length; j++)

                  System.out.println(

                    "exc #" + j + " " + evec[j]);

               System.out.println("-----");

            }

          }

          catch (Throwable e) {

             System.err.println(e);

          }

      }

   }



Constructor ctorlist[] = cls.getDeclaredConstructors():获取该实例对象声明的所有的构造函数数组。

ct.getName():获取该构造函数的名称,返回值是一个字符串类型的变量。

ct.getDeclaringClass():返回声明该构造函数的类。返回值是一个class。

Class pvec[] = ct.getParameterTypes():返回该构造函数的参数的一个类型数组。返回的是一个class类型的数组。

Class evec[] = ct.getExceptionTypes():返回一个该构造函数的抛出的例外的一个类型数组。

除了上述的方法外,对于Constructor类还有一个很重要的方法:

Object newInstance(Object iniargs[]):实际调用该构造函数并且生成一个实例对象。具体的应用参看3.5节。

3.3 获取类中域的信息
import java.lang.reflect.*;

        

   public class field1 {

      private double d;

      public static final int i = 37;

      String s = "testing";

        

      public static void main(String args[])

      {

         try {

            Class cls = Class.forName("field1");

        

            Field fieldlist[]

              = cls.getDeclaredFields();

            for (int i

              = 0; i < fieldlist.length; i++) {

               Field fld = fieldlist[i];

               System.out.println("name

                  = " + fld.getName());

               System.out.println("decl class = " +

                           fld.getDeclaringClass());

               System.out.println("type

                  = " + fld.getType());

               int mod = fld.getModifiers();

               System.out.println("modifiers = " +

                          Modifier.toString(mod));

               System.out.println("-----");

            }

          }

          catch (Throwable e) {

             System.err.println(e);

          }

       }

   }

3.4 通过方法名调用方法
import java.lang.reflect.*;

        

   public class method2 {

      public int add(int a, int b)

      {

         return a + b;

      }

        

      public static void main(String args[])

      {

         try {

           Class cls = Class.forName("method2");

           Class partypes[] = new Class[2];

            partypes[0] = Integer.TYPE;

            partypes[1] = Integer.TYPE;

            Method meth = cls.getMethod(

              "add", partypes);

            method2 methobj = new method2();

            Object arglist[] = new Object[2];

            arglist[0] = new Integer(37);

            arglist[1] = new Integer(47);

            Object retobj

              = meth.invoke(methobj, arglist);

            Integer retval = (Integer)retobj;

            System.out.println(retval.intValue());

         }

         catch (Throwable e) {

            System.err.println(e);

         }

      }

   }

       我们会仔细地介绍方法调用的实现。

首先,声明了一个类method2,该类有一个方法public int add(int a, int b)。请注意该方法的方法名’add’、两个形式参数的数据类型int以及返回值类型int。因为,这些信息对动态地调用一个类的方法是非常重要的。

       接下来在主调函数中实现的功能如下:

1.Class cls = Class.forName("method2"):获取类实例对象cls。

2.Class partypes[] = new Class[2];

   partypes[0] = Integer.TYPE;

   partypes[1] = Integer.TYPE;

声明一个类数组,用来保存两个参数的数据类型。

3.Method meth = cls.getMethod("add", partypes);注意getMethod方法,该方法将返回一个匹配的方法。匹配的条件,有两部分来限定。一个是方法名,一个是方法的参数类型数组。(因为JAVA中允许方法的重载,所以必须说明参数的数据类型)参数类型数组中的各个参数类型的顺序必须与方法声明时的顺序相同。

4.method2 methobj = new method2():声明一个类method2的实例变量。

5.Object arglist[] = new Object[2];

   arglist[0] = new Integer(37);

   arglist[1] = new Integer(47);

声明一个对象数组,来存储两个参数实例。

6.Object retobj  = meth.invoke(methobj, arglist):实际调用add函数。注意方法invoke()的两个参数,methobj是调用方法(或者是声明方法)的类的一个实例,arglist确实被调用方法(这里是add方法)的,参数实例数组。返回值仍然是一个对象的实例retobj。

7.Integer retval = (Integer)retobj;

   System.out.println(retval.intValue());将返回的对象实例,进行类型转换,并输出。

3.5 生成一个新的实例
import java.lang.reflect.*;

        

   public class constructor2 {

      public constructor2()

      {

      }

        

      public constructor2(int a, int b)

      {

         System.out.println(

           "a = " + a + " b = " + b);

      }

        

      public static void main(String args[])

      {

         try {

           Class cls = Class.forName("constructor2");

           Class partypes[] = new Class[2];

            partypes[0] = Integer.TYPE;

            partypes[1] = Integer.TYPE;

            Constructor ct

              = cls.getConstructor(partypes);

            Object arglist[] = new Object[2];

            arglist[0] = new Integer(37);

            arglist[1] = new Integer(47);

            Object retobj = ct.newInstance(arglist);

         }

         catch (Throwable e) {

            System.err.println(e);

         }

      }

   }

这个例子说明了Constructor类的newInstancce()方法的使用。