Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
方法声明包括名称,修饰符,参数,返回类型和可抛出异常列表。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()
将参考
类文件中的签名属性(如果存在)。如果该属性不可用,则它将返回 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
,因为泛型是通过 type erasure (类型擦除)实现的,其在编译期间移除有关泛型类型的所有信息。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
显示。