获取方法类型信息
方法声明包括名称,修饰符,参数,返回类型和可抛出异常的列表。 java.lang.reflect.Method类提供了一种获取此信息的方法。
MethodSpy示例说明了如何枚举给定类中的所有已声明方法,以及如何检索给定名称的所有方法的返回,参数和异常类型。
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import static java.lang.System.out;
public class MethodSpy {
private static final String fmt = "%24s: %s%n";
// for the morbidly curious
<E extends RuntimeException> void genericThrow() throws E {}
public static void main(String... args) {
try {
Class<?> c = Class.forName(args[0]);
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
if (!m.getName().equals(args[1])) {
continue;
}
out.format("%s%n", m.toGenericString());
out.format(fmt, "ReturnType", m.getReturnType());
out.format(fmt, "GenericReturnType", m.getGenericReturnType());
Class<?>[] pType = m.getParameterTypes();
Type[] gpType = m.getGenericParameterTypes();
for (int i = 0; i < pType.length; i++) {
out.format(fmt,"ParameterType", pType[i]);
out.format(fmt,"GenericParameterType", gpType[i]);
}
Class<?>[] xType = m.getExceptionTypes();
Type[] gxType = m.getGenericExceptionTypes();
for (int i = 0; i < xType.length; i++) {
out.format(fmt,"ExceptionType", xType[i]);
out.format(fmt,"GenericExceptionType", gxType[i]);
}
}
// production code should handle these exceptions more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
这是Class.getConstructor()的输出,这是具有参数化类型和可变数量参数的方法的示例。
$ java MethodSpy java.lang.Class getConstructor
public java.lang.reflect.Constructor<T> java.lang.Class.getConstructor
(java.lang.Class<?>[]) throws java.lang.NoSuchMethodException,
java.lang.SecurityException
ReturnType: class java.lang.reflect.Constructor
GenericReturnType: java.lang.reflect.Constructor<T>
ParameterType: class [Ljava.lang.Class;
GenericParameterType: java.lang.Class<?>[]
ExceptionType: class java.lang.NoSuchMethodException
GenericExceptionType: class java.lang.NoSuchMethodException
ExceptionType: class java.lang.SecurityException
GenericExceptionType: class java.lang.SecurityException
这是源代码中方法的实际声明:
public Constructor<T> getConstructor(Class<?>... parameterTypes)
首先请注意,返回值和参数类型是通用的。 Method.getGenericReturnType()将查询类文件中的 Signature 属性(如果存在)。如果该属性不可用,它会退回到Method.getReturnType(),而引入泛型并没有改变该属性。对于反射中* Foo *的某个值,名称为getGenericFoo()
的其他方法也类似地实现。
接下来,请注意最后一个(也是唯一一个)参数parameterType
具有类型java.lang.Class
的可变变量(具有可变数量的参数)。它表示为java.lang.Class
类型的一维数组。通过调用Method.isVarArgs(),可以将其与显式为java.lang.Class
数组的参数区分开。 Method.get*Types()
的返回值的语法在Class.getName()中描述。
以下示例说明了具有通用返回类型的方法。
$ java MethodSpy java.lang.Class cast
public T java.lang.Class.cast(java.lang.Object)
ReturnType: class java.lang.Object
GenericReturnType: T
ParameterType: class java.lang.Object
GenericParameterType: class java.lang.Object
方法Class.cast()的泛型返回类型报告为java.lang.Object
,因为泛型是通过类型擦除实现的,该类型擦除会在编译过程中删除有关泛型类型的所有信息。 T
的擦除由Class的声明定义:
public final class Class<T> implements ...
因此T
被类型变量的上限(在这种情况下为java.lang.Object
)替换。
最后一个示例说明了具有多个重载的方法的输出。
$ java MethodSpy java.io.PrintStream format
public java.io.PrintStream java.io.PrintStream.format
(java.util.Locale,java.lang.String,java.lang.Object[])
ReturnType: class java.io.PrintStream
GenericReturnType: class java.io.PrintStream
ParameterType: class java.util.Locale
GenericParameterType: class java.util.Locale
ParameterType: class java.lang.String
GenericParameterType: class java.lang.String
ParameterType: class [Ljava.lang.Object;
GenericParameterType: class [Ljava.lang.Object;
public java.io.PrintStream java.io.PrintStream.format
(java.lang.String,java.lang.Object[])
ReturnType: class java.io.PrintStream
GenericReturnType: class java.io.PrintStream
ParameterType: class java.lang.String
GenericParameterType: class java.lang.String
ParameterType: class [Ljava.lang.Object;
GenericParameterType: class [Ljava.lang.Object;
如果发现多个具有相同方法名称的重载,则它们全部由Class.getDeclaredMethods()返回。由于format()
有两个重载(带有Locale的重载和一个没有重载的重载),因此都由MethodSpy
表示。
Note:
Method.getGenericExceptionTypes()之所以存在,是因为实际上可以声明具有通用异常类型的方法。但是,由于无法catch通用异常类型,因此很少使用。