Java反射-类

时间:2020-01-09 14:20:02  来源:igfitidea点击:

使用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();