Java反射-类
使用Java Reflection,我们可以在运行时检查Java类。在使用反射时,检查类通常是我们要做的第一件事。从这些类中,我们可以获得有关以下内容的信息
- 类名
- 类修改(public、private、synchronized等)
- 程序包信息
- 超类
- 实现的接口
- 构造函数
- 方法
- 字段
- 注释
以及有关Java类的更多信息。有关完整列表,请查阅JavaDoc中的java.lang.Class。本文将简要介绍上述信息的所有访问。一些主题还将在单独的文本中进行更详细的研究。例如,本文将向我们展示如何获取所有方法或者特定方法,而单独的文本将向我们展示如何调用该方法,如果存在多个方法,则如何查找与给定参数集匹配的方法。同名,通过反射从方法调用中引发了什么异常,如何发现getter / setter等。本文的目的主要是介绍" Class"对象以及我们可以从中获取的信息。
类对象
在对类进行任何检查之前,需要获取其" java.lang.Class"对象。 Java中的所有类型(包括基元类型(int,long,float等),包括数组)都具有关联的" Class"对象。如果我们在编译时知道类的名称,则可以这样获取Class
对象:
Class myObjectClass = MyObject.class
如果我们在编译时不知道名称,但在运行时将类名称作为字符串,则可以执行以下操作:
String className = ... //在运行时获取类名称作为字符串Class class = Class.forName(className);
使用Class.forName()方法时,必须提供完全限定的类名。那是包含所有包名称的类名称。例如,如果MyObject位于包com.Hyman.myapp
中,则完全限定的类名称为com.Hyman.myapp.MyObject
。
如果在运行时无法在类路径上找到该类,则Class.forName()方法可能会抛出ClassNotFoundException。
类名
从"类"对象中,我们可以获得两种版本的名称。完全合格的类名(包括包名)是使用getName()方法获得的,如下所示:
Class aClass = ... //obtain Class object. See prev. section String className = aClass.getName();
如果我们想要没有pacakge名称的类名,则可以使用getSimpleName()方法获取它,如下所示:
Class aClass = ... //obtain Class object. See prev. section String simpleClassName = aClass.getSimpleName();
修饰符
我们可以通过Class对象访问类的修饰符。类修饰符是关键字" public"," private"," static"等。我们可以这样获得类修饰符:
Class aClass = ... //obtain Class object. See prev. section int modifiers = aClass.getModifiers();
修饰符打包到一个" int"中,其中每个修饰符都是一个已设置或者清除的标志位。我们可以在类java.lang.reflect.Modifier
中使用以下方法检查修饰符:
Modifier.isAbstract(int modifiers) Modifier.isFinal(int modifiers) Modifier.isInterface(int modifiers) Modifier.isNative(int modifiers) Modifier.isPrivate(int modifiers) Modifier.isProtected(int modifiers) Modifier.isPublic(int modifiers) Modifier.isStatic(int modifiers) Modifier.isStrict(int modifiers) Modifier.isSynchronized(int modifiers) Modifier.isTransient(int modifiers) Modifier.isVolatile(int modifiers)
包信息
我们可以从Class
对象获取有关软件包的信息,如下所示:
Class aClass = ... //obtain Class object. See prev. section Package package = aClass.getPackage();
从"包"对象中,我们可以访问有关包的信息,例如其名称。我们还可以在位于类路径上的JAR文件的"列表"文件中访问为此包指定的信息。例如,我们可以在"列表"文件中指定软件包的版本号。我们可以在此处阅读有关Package
类的更多信息:java.lang.Package
超类
从"类"对象中,我们可以访问该类的超类。方法如下:
Class superclass = aClass.getSuperclass();
超类类对象是一个" Class"对象,因此我们也可以继续对此进行类反射。
已实现的接口
可以获取由给定类实现的接口的列表。方法如下:
Class aClass = ... //obtain Class object. See prev. section Class[] interfaces = aClass.getInterfaces();
一个类可以实现许多接口。因此,返回一个" Class"数组。接口也由Java Reflection中的"类"对象表示。
注意:仅返回由给定类明确声明实现的接口。如果该类的超类实现了一个接口,但是该类未明确声明它也实现了该接口,则该接口将不会在数组中返回。即使实际上该类实现了该接口,因为超类也是如此。
为了获得由给定类实现的接口的完整列表,我们将必须递归地查询该类及其超类。
构造函数
我们可以像这样访问类的构造函数:
Constructor[] constructors = aClass.getConstructors();
构造函数在构造函数的文本中有更详细的介绍。
方法
我们可以像下面这样访问类的方法:
Method[] method = aClass.getMethods();
有关方法的详细信息,请参见方法。
字段
我们可以像这样访问类的字段(成员变量):
Field[] method = aClass.getFields();
在"字段"中的文本中更详细地介绍了字段。
注释
我们可以像下面这样访问类的类注释:
Annotation[] annotations = aClass.getAnnotations();