`

java.lang.reflect.Method

阅读更多
package java.lang.reflect;

import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;

/**
 * 
 * 描述方法的类
 * 
 * 注意使用反射的方式是首先通过
 * Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
 * String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
 * Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
 * 这里obj指调用方法的对象,args表示每个参数对应的值
 * 
 * 例子,一下两种方式的效果是一样的(当然性能不同)
 * String ost = "lqtest";
 * String nst = ost.substring(2,6);
 * 
 * String ost2 = "lqtest";
 * Class[] types = {int.class, int.class};
 * Method med = String.class.getMethod("substring", types);
 * Object[] values ={new Integer(2), new Integer(6)};
 * String nst2 = (String) med.invoke(ost2, values);
 * 
 * 使用反射一切都是变化的,类名,方法名,参数列表,都是变量,而不是写死的,他们
 * 在运行时才知道具体值,而不是编译期
 * 
 * comment by liqiang
 *
 * @author Kenneth Russell
 * @author Nakul Saraiya
 */
public final
class Method extends AccessibleObject implements Member {
 //定义此方法的类对象
    private Class  clazz;
    private int   slot;
    //方法名,从1.4开始它变成intern的形式
    private String  name;
    //返回类型
    private Class  returnType;
    //参数列表
    private Class[]  parameterTypes;
    //异常列表
    private Class[]  exceptionTypes;
    //方法的描述符
    private int   modifiers;
    //处理方法的实际对象
    private volatile MethodAccessor methodAccessor;
    //如果当前对象是通过拷贝得到的,则root指向拷贝前的对象
    private Method              root;

    //调用对象的安全检查的缓存,保存上一个通过检查的调用对象,如果当前的调用对象
    //不是上一个调用对象则做安全检查
    private volatile Class      securityCheckTargetClassCache;

    //构造函数
    Method(Class declaringClass,
           String name,
           Class[] parameterTypes,
           Class returnType,
           Class[] checkedExceptions,
           int modifiers,
           int slot)
    {
        this.clazz = declaringClass;
        this.name = name;
        this.parameterTypes = parameterTypes;
        this.returnType = returnType;
        this.exceptionTypes = checkedExceptions;
        this.modifiers = modifiers;
        this.slot = slot;
    }

    //通过本对象的数据生成一个新对象
    Method copy() {
     //通过本对象的数据生成一个新对象
        Method res = new Method(clazz, name, parameterTypes, returnType,
                                exceptionTypes, modifiers, slot);
        //新对象的root指向原对象
        res.root = this;
        //新对象与原对象公用一个MethodAccessor
        res.methodAccessor = methodAccessor;
        return res;
    }

    //返回声明此函数的类
    public Class getDeclaringClass() {
 return clazz;
    }

    //返回方法名
    public String getName() {
 return name;
    }

    //返回描述符
    public int getModifiers() {
 return modifiers;
    }

    //取得返回类型
    public Class getReturnType() {
 return returnType;
    }

    //返回参数列表
    public Class[] getParameterTypes() {
 return copy(parameterTypes);
    }

    //返回异常列表
    public Class[] getExceptionTypes() {
 return copy(exceptionTypes);
    }

    //判断obj是否与当前方法对象相等
    public boolean equals(Object obj) {
 if (obj != null && obj instanceof Method) {//如果是方法对象
  //转型
     Method other = (Method)obj;
     
     //定义此方法的类和方法名相等
     if ((getDeclaringClass() == other.getDeclaringClass())
  && (getName() == other.getName())) {
      
  /* Avoid unnecessary cloning */
  Class[] params1 = parameterTypes;
  Class[] params2 = other.parameterTypes;
  
  //比较参数列表
  if (params1.length == params2.length) {
      for (int i = 0; i < params1.length; i++) {
   if (params1[i] != params2[i])
       return false;
      }
      return true;
  }
  
     }
 }
 return false;
    }

    //返回hashCode
    public int hashCode() {
 return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
    }

    //方法对象的字符串表示
    public String toString() {
 try {
     StringBuffer sb = new StringBuffer();
     int mod = getModifiers();
     if (mod != 0) {
     //标志符
  sb.append(Modifier.toString(mod) + " ");
     }
     //注意它这里用的是Field方法中显示类的名字,这个方法显示数组类型跟Class.getName()不同
     //添加返回类型
     sb.append(Field.getTypeName(getReturnType()) + " ");
     //添加类名
     sb.append(Field.getTypeName(getDeclaringClass()) + ".");
     //添加方法名
     sb.append(getName() + "(");    
     
     //参数列表
     Class[] params = parameterTypes; // avoid clone
     for (int j = 0; j < params.length; j++) {
  sb.append(Field.getTypeName(params[j]));
  if (j < (params.length - 1))
      sb.append(",");
     }
     sb.append(")");
     
     //异常列表
     Class[] exceptions = exceptionTypes; // avoid clone
     if (exceptions.length > 0) {
  sb.append(" throws ");
  for (int k = 0; k < exceptions.length; k++) {
      sb.append(exceptions[k].getName());
      if (k < (exceptions.length - 1))
   sb.append(",");
  }
     }
     return sb.toString();
 } catch (Exception e) {
     return "<" + e + ">";
 }
    }

    /**
     * 
     * 注意使用反射的方式是首先通过
     * Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
     * String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
     * Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
     * 如果调用的方法是static的则obj对象为null,如果方法没有参数,则args的长度为0或为null
     * 如果返回值是原始类型则返回它的封装类,如果返回值是void则返回null
     */
    public Object invoke(Object obj, Object[] args)
 throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
             //获得调用对象的Class对象
                Class caller = Reflection.getCallerClass(1);
                
                Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))
                                     ? clazz
                                     : obj.getClass());
                //调用此操作的对象或方法调用作用的对象与缓存不同,则做安全检查
                if (securityCheckCache != caller ||
                    targetClass != securityCheckTargetClassCache) {
                    Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
                    securityCheckCache = caller;
                    //通过安全检查的调用对象,缓存它供下次调用时使用
                    securityCheckTargetClassCache = targetClass;
                }
            }
        }
        
        if (methodAccessor == null) acquireMethodAccessor();
        return methodAccessor.invoke(obj, args);
    }

    //如果此对象是由copy生成的,则对象与生成此对象的对象使用同一个MethodAccessor
    private void acquireMethodAccessor() {
        MethodAccessor tmp = null;
        
        if (root != null) tmp = root.getMethodAccessor();
        if (tmp != null) {
            methodAccessor = tmp;
            return;
        }
        
        //不是由copy得来创建MethodAccessor对象
        tmp = reflectionFactory.newMethodAccessor(this);
        setMethodAccessor(tmp);
    }

    //返回MethodAccessor对象
    MethodAccessor getMethodAccessor() {
        return methodAccessor;
    }

    //设置MethodAccessor对象
    void setMethodAccessor(MethodAccessor accessor) {
        methodAccessor = accessor;
        if (root != null) {//如果此对象是由copy的来
         //递归调用其上级
            root.setMethodAccessor(accessor);
        }
    }

    //生成一个新的Class数组并将原数组内容考到新数组中
    static Class[] copy(Class[] in) {
 int l = in.length;
 
 if (l == 0)
     return in;
 
 Class[] out = new Class[l];
 for (int i = 0; i < l; i++)
     out[i] = in[i];
 
 return out;
    }
}

 

分享到:
评论

相关推荐

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

    `InvocationTargetException`通常作为Java标准库中的`java.lang.reflect.Method.invoke()`方法的异常包装器。当目标方法抛出异常时,`invoke()`会捕获这个异常并封装为`InvocationTargetException`,然后将其抛出。...

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

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

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

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

    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...

    server frame base on c.rar

    java.lang.NullPointerException ... at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80)

    JAVA反射实现和实现机制

    4. **`java.lang.reflect.Method`**:表示类的方法。 5. **`java.lang.reflect.Modifier`**:提供对成员的修饰符的访问。 ##### 基本使用方法 1. **获取成员方法信息**: - `Method[] getMethods()`:获取公开的...

    Android平台与Web服务数据交互时运用Java反射机制解析数据的研究.pdf

    其中最经常使用的是三个类:java.lang.reflect.Field类、java.lang.reflect.Method类和java.lang.reflect.Constructor类。 Java.lang.reflect.Field类提供了有关类或接口的单个域的信息。利用这个类,我们可以得到...

    javassist3.19GA.jar

    用以执行和JDK反射API中java.lang.Class,,java.lang.reflect.Method,, java.lang.reflect.Method .Field相同的操作。这些类可以使你在目标类被加载前,轻松的获得它的结构,函数,以及属性。此外,不仅仅是在功能...

    ExcelExportUtils.java

    import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util....

    java Reflection 反射机制 反编译

    import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectionTest { public static void main(String[] args) { Class c = null; try { c = Class.forName("java.lang....

    java的类反射

    反射的核心类包括`java.lang.Class`、`java.lang.reflect.Field`、`java.lang.reflect.Method`和`java.lang.reflect.Constructor`。下面将详细阐述这些核心类以及反射的主要用法。 1. `java.lang.Class`:每个类在...

    android 奔溃日志收集 发送邮件到邮箱

    集成邮件工具类,用于发送某个应用的奔溃日志信息到邮箱。...at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:10

    【Java基础笔记】反射.docx

    在Java中,反射主要涉及到`java.lang.Class`、`java.lang.reflect.Method`、`java.lang.reflect.Field`和`java.lang.reflect.Constructor`等类。下面将详细介绍这些知识点。 1. **反射的概述** 反射机制使得Java...

    java反射机制[参照].pdf

    反射机制的核心在于Java Reflection API,其中包括`java.lang.Class`,`java.lang.reflect.Method`,`java.lang.reflect.Field`和`java.lang.reflect.Constructor`等类。 首先,`java.lang.Class`是所有Java类的元...

    Java动态代理自建注解

    Java的`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口提供了实现动态代理的基础设施。`InvocationHandler`接口定义了一个`invoke`方法,它会在代理对象调用原对象的方法时被触发。我们...

    java面试题--反射机制

    Object result = method.invoke(obj, "Hello, World!"); System.out.println(result); // 输出: Hello, World! // 获取字段 Field field = clazz.getDeclaredField("value"); field.setAccessible(true); ...

    Java EE:Reflect 反射技术.docx

    method.invoke(obj, 参数...);` 5. 反射的注意事项: - 安全性:反射可以访问私有成员,但这也可能导致安全问题,因为它破坏了封装性。 - 性能:反射操作通常比直接调用方法或访问属性慢,因此在性能敏感的代码中...

    Java语言的动态属性总结[参考].pdf

    3. **Java.lang.reflect.Method**: 代表类的方法信息,包括方法名、返回类型和参数列表。通过`Method`对象,我们可以调用一个类的静态或实例方法。 4. **Java.lang.reflect.Field**: 描述类的字段,包括字段的类型...

    java 反射例子 代码

    java.lang.reflect.Constructor; java.lang.reflect.Field; java.lang.reflect.Method; java.lang.reflect.Modifier;

Global site tag (gtag.js) - Google Analytics