`
wangyong
  • 浏览: 41531 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Java.lang.reflect包介绍

    博客分类:
  • JAVA
阅读更多

特此声明这些资料的原始内容来自www.java.sun.com,本人只是对其内容在个人的理解的基础上,进行翻译和整理。
一.概述
       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()方法的使用。其具体的过程与3.4节中使用invoke()方法类似,不再多说了。

分享到:
评论

相关推荐

    scrcpy投屏 AssertionError: java.lang.reflect.InvocationTargetExcep

    标题中的问题“scrcpy投屏 AssertionError: java.lang.reflect.InvocationTargetException”是用户在尝试使用Scrcpy时遇到的一个常见错误。这个错误通常意味着在执行某个方法时,Java运行时环境遇到了未预期的情况。...

    Java.lang.reflect 包下常用的类及方法简介

    在Java编程语言中,`java.lang.reflect`包是核心库的一部分,它提供了运行时访问类、接口、字段和方法的能力。这个包对于理解和操作对象的动态特性至关重要,尤其是在实现反射机制时。反射允许我们在程序运行期间...

    解决axis2-CodegenWizardPluginBUG- java.lang.reflect.InvocationTargetException

    标题中的“解决axis2-CodegenWizardPluginBUG- java.lang.reflect.InvocationTargetException”指的是在使用Apache Axis2的CodegenWizardPlugin工具时遇到的一个错误。这个工具是Axis2框架的一部分,用于自动生成...

    java.lang.reflect.Proxy 学习资料 讲解 例子 源码

    java.lang.reflect.Proxy 学习资料 讲解 例子 源码 java.lang.reflect.Proxy 学习资料 讲解 例子 源码 java.lang.reflect.Proxy 学习资料 讲解 例子 源码

    MyEclipse axis2 wsdl java.lang.reflect.invocationtargetexception

    MyEclipse axis2 wsdl java.lang.reflect.invocationtargetexception code gen 大家要注意一定要仔细,这个问题基本上缺少包引起的,而且一定要clean 如果需要axis2插件 以及这个plugins中的包在我的其他资源里面有

    WebLogic错误 java.lang.AssertionError: Registered more than one

    Caused by: java.lang.RuntimeException: javax.management.remote.JMXServerErrorException: java.lang.AssertionError: Registered more than one instance with the same objectName : com.bea:Name=wl04,Type=...

    Java reflect 机制详解

    免费共享,很详细的介绍了反射机制的原理,适合追根究底的java学习者

    commons-lang3-3.1jar:org.apache.commons.lang3.StringUtils等.

    `org.apache.commons.lang3.reflect.FieldUtils`类则是关于反射操作的工具类,它提供了一些安全且方便的方法来访问和修改对象的字段。这些方法包括但不限于: 1. `getField()`:安全地获取类或对象的字段,即使该...

    BEWINDOWEB#bewindoweb.github.io#00078-编写basedao的时候报错:java.lang.C

    编写basedao的时候报错:java.lang.Class cannot be cast to java.lang.reflect.Parameterized

    Java常用包介绍.pdf

    java.lang.reflect 包提供了用于反射对象的工具,包括类、字段、方法和构造方法的反射。 6. java.awt.image 包 java.awt.image 包处理和操纵来自于网上的图片的Java工具类库,包括图像处理、图像resize和图像滤镜...

    jaxen.jar和dom4j.jar

    at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run...

    axis2 InvocationTargetException

    标题 "axis2 InvocationTargetException" 描述的是一个与Apache Axis2框架相关的编程问题,该问题通常在执行服务调用时出现,提示"InvocationTargetException"。这可能是由于多种原因引起的,包括但不限于错误的服务...

    JAVA反射实现和实现机制

    5. **`java.lang.reflect.Modifier`**:提供对成员的修饰符的访问。 ##### 基本使用方法 1. **获取成员方法信息**: - `Method[] getMethods()`:获取公开的方法。 - `Method getMethod(String name, Class&lt;?&gt;.....

    wsdl生成java客户端报错

    java.lang.reflect.invocationtargetexception问题的解决方法之一

    aop面向切面需要的jar包

    Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.Access...

    Java核心API

    Java.lang.reflect包提供了在运行时分析代码结构和行为的能力,是实现反射、动态代理等功能的基础。 #### Java.math Java.math包处理大整数和十进制数运算,对于高精度计算至关重要。 #### Java.net Java.net包...

    API规范JAVA.pdf

    * java.lang.reflect 是 Java 2 Platform 的一部分,提供了类和接口,以获得关于类和对象的反射信息。 20、数学运算:java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类...

    java 请求的方法不存在(NoSuchMethodException)

    3. **Java动态代理**:基于`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`,实现对目标对象的代理,用于拦截方法调用。 综上所述,`NoSuchMethodException`是Java编程中需要关注的一个重要异常...

Global site tag (gtag.js) - Google Analytics