18.3. 2从Class中获取信息
Class类提供了大量的实例方法来获取该Class对象所对应类的详细信息, Class类大致包含如下方法,下面每个方法都可能包括多个重载的版本,读者应该查阅API文档来掌握它们。
获取构造器
下面4个方法用于获取Class对应类所包含的构造器
| 方法 | 描述 |
|---|---|
Constructor<T> getConstructor(Class<?>...parameter Types) |
返回此Class对象对应类的、带指定形参列表的public构造器。 |
Constructor<?>[] getConstructors() |
返回此 Class对象对应类的所有public构造器。 |
Constructor<T> getDeclaredConstructor( Class<?>...parameterTypes) |
返回此 Class对象对应类的带指定形参列表的构造器,与构造器的访问权限无关。 |
Constructor<?>[] getDeclaredConstructors() |
返回此 Class对象对应类的所有构造器,与构造器的访问权限无关。 |
获取方法
下面4个方法用于获取Class对应类所包含的方法。
| 方法 | 描述 |
|---|---|
Method getMethod(String name, Classs<?> ... parameterTypes) |
返回此Class对象对应类的、带指定形参列表的 public方法。 |
Method[] getMethods() |
返回此Class对象所表示的类的所有 public方法。 |
Method getDeclaredMethod(String name, Class<?> ... parameter Types) |
返回此 Class对象对应类的、带指定形参列表的方法,与方法的访问权限无关。 |
Method[] getDeclaredMethods() |
返回此Class对象对应类的全部方法,与方法的访问权限无关 |
获取成员变量
如下4个方法用于访问Class对应类所包含的成员变量。
| 方法 | 描述 |
|---|---|
Field getField(String name) |
返回此 Class对象对应类的、指定名称的 public成员变量。 |
Field[] getFields() |
返回此Class对象对应类的所有 public成员变量。 |
Field getDeclaredField(String name) |
返回此 Class对象对应类的、指定名称的成员变量,与成员变量的访问权限无关。 |
Field[] getDeclaredFields() |
返回此 Class对象对应类的全部成员变量,与成员变量的访问权限无关 |
获取Annotation
如下几个方法用于访问Class对应类上所包含的Annotation
| 方法 | 描述 |
|---|---|
<A extends Annotation> A getAnnotation(Class<A> annotationClass |
尝试获取该 Class象对应类上存在的、指定类型的 Annotation;如果该类型的注解不存在,则返回null。 |
Annotation[] getAnnotations() |
返回修饰该 Class对象对应类上存在的所有 Annotation |
<A extends annotation> A getDeclaredAnnotation(Class<A> annotationClass) |
这是Java 8新增的方法,该方法尝试获取直接修饰该Class对象对应类的、指定类型的Annotation;如果该类型的注解不存在,则返回null。 |
Annotation[] getDeclaredAnnotations() |
返回直接修饰该Class对应类的所有 Annotation |
<A extends Annotation> A getAnnotationsByType(Class<A> annotationClass) |
该方法的功能与前面介绍的getAnnotation()方法基本相似。但由于Java 8增加了重复注解功能,因此需要使用该方法获取修饰该类的、指定类型的多个Annotation |
| ## 获取包含的内部类 ## | |
如下方法用于访问该Class对象对应类包含的内部类。 |
| 方法 | 描述 |
|---|---|
Class<?> getClasses() |
返回该Class对象对应类里包含的全部内部类。 |
| ## 获取所在的外部类 ## | |
如下方法用于访问该Class对象对应类所在的外部类。 |
| 方法 | 描述 |
|---|---|
Class<?> getDeclaringClass() |
返回该Class对象对应类所在的外部类 |
| ## 访问该Class对象对应类所实现的接口 ## | |
如下方法用于访问该Class对象对应类所实现的接口 |
| 方法 | 描述 |
|---|---|
Classs<?>[] getInterfaces() |
返回该Class对象对应类所实现的全部接口。 |
| ## 获取所继承的父类 ## | |
如下几个方法用于访问该Class对象对应类所继承的父类。 |
| 方法 | 描述 |
|---|---|
Class<? super T> getSuperClass() |
返回该Class对象对应类的超类的Class对象。 |
| ## 获取修饰符 所在包 类名等基本信息 ## | |
如下方法用于获取Class对象对应类的修饰符、所在包、类名等基本信息。 |
| 方法 | 描述 |
|---|---|
int getModifiers() |
返回此类或接口的所有修饰符。修饰符由 public、 protected、 private、final、static、 abstract等对应的常量组成,返回的整数应使用 Modifier工具类的方法来解码,才可以获取真实的修饰符。 |
Package getPackage() |
获取此类的包。 |
String getName() |
以字符串形式返回此Class象所表示的类的名称。 |
String getSimpleName() |
以字符串形式返回此Class对象所表示的类的简称。 |
| ## 判断该类是否为接口 枚举 注解类型 ## | |
除此之外, Class对象还可调用如下几个判断方法来判断该类是否为接口、枚举、注解类型等。 |
| 方法 | 描述 |
|---|---|
boolean isAnnotation() |
返回此Class对象是否表示一个注解类型(由@interface定义) |
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) |
判断此Class对象是否使用了Annotation修饰 |
boolean isAnonymousClass() |
返回此Class对象是否是一个匿名类。 |
boolean isArray() |
返回此Class对象是否表示一个数组类。 |
boolean isEnum() |
返回此Class象是否表示一个枚举(由enum关键字定义)。 |
boolean isInterface() |
返回此 Class对象是否表示一个接口(使用 interface定义)。 |
boolean isInstance(Object object) |
判断object是否是此Class对象的实例,该方法可以完全代替instanceof操作符。 |
如何通过反射获取一个方法
上面的多个getMethod()方法和getConstructor()方法中,都需要传入多个类型为Classs<?>的参数,用于获取指定的方法或指定的构造器。关于这个参数的作用,假设某个类内包含如下三个info方法签名。
public void info()public void info(String str)public void info(String str,Integer num)
这三个同名方法属于重载,它们的方法名相同,但参数列表不同。在Java语言中如果需要确定一个方法,则应该由方法名和形参列表来确定,但形参名没有任何实际意义,所以只能由形参类型来确定。例如想指定第二个info方法,则必须指定:
- 方法名为
info, - 形参列表为
String.class
因此在程序中获取该方法使用如下代码:
clazz.getMethod("info", String.class)- 前一个参数指定方法名,后面的个数可变的
Class参数指定形参类型列表。
- 前一个参数指定方法名,后面的个数可变的
如果需要获取第三个info方法,则使用如下代码:
clazz.getMethod("info", String.class, Integer.class)- 前一个参数指定方法名,后面的个数可变的
Class参数指定形参类型列表。
- 前一个参数指定方法名,后面的个数可变的
如何通过反射获取一个构造器
获取构造器时无须传入构造器名—同一个类的所有构造器的名字都是相同的,所以要确定一个构造器只要指定形参列表即可。
程序示例
下面程序示范了如何通过该Class对象来获取对应类的详细信息。
1 | import java.util.*; |
上面程序获取了ClassTest类对应的Class对象后,通过调用该Class对象的不同方法来得到该Class对象的详细信息。运行结果如下:
1 | ClassTest的全部构造器如下: |
从上面运行结果来看, Class提供的功能非常丰富,它可以获取该类里包含的构造器、方法、内部类、注解等信息,也可以获取该类所包括的成员变量(Field)信息。
Class无法获取值显示在源代码上的注解
值得指出的是,虽然定义ClassTest类时使用了 @SuppressWarnings注解,但程序运行时无法分析出该类里包含的该注解,这是因为@SuppressWarnings使用了@Retention(value= SOURCE)修饰,这表明@SuppressWarnings只能保存在源代码级别上,而通过ClassTest.class取该类的运行时Class对象,所以程序无法访问到@SuppressWarnings注解。
对于只能在源代码上保留的注解,使用运行时获得的Class对象无法访问到该注解对象。
通过Class对象可以得到大量的Method、 Constructor、 Field等对象,这些对象分别代表该类所包括的方法、构造器和成员变量等,程序还可以通过这些对象来执行实际的功能,例如调用方法、创建实例。
本文重点
通过Class类,
- 可以获取对应类的构造器
- 可以获取对应类中方法
- 获取对应类的成员变量
- 获取对应类的
Annotation - 获取对应类包含的内部类
- 获取对应类所在的外部类
- 获取对应类所实现的接口
- 获取对应类所继承的父类
- 获取对应类的修饰符 所在包 类名等基本信息
- 可以判断对应类是否为接口 枚举 注解类型
- 在获取方法时需要传入方法名和参数列表,
- 在获取构造器时只需要传入参数列表。
Class无法获取值显示在源代码上的注解,例如@SuppressWarnings注解无法通过反射获取
原文链接: 18.3.2 从Class中获取信息