java核心学习(三十八) 通过反射查看类信息

  反射实现了java代码对java代码的操作。

一、获得Class对象

  有下列四种方式:

  •     使用Class类的forName(String className) 静态方法,该静态方法需要传入类的全限定名称字符串。
  •     调用某个类的class属性来获得该类对应的class对象。
  •     调用某个对象的getClass()方法。
  •     调用ClassLoader实例对象的loadClass方法。

  由前两节对类加载的学习,可以了解到使用第二种和第三种方法获得Class对象,JVM已经将该类初始化,第三种方法由于创建了该类的实例,所以还会初始化该类的一个对象(及执行了非静态变量赋值+初始化代码块+构造函数)。

  使用第一种方式,通过查看forName方法的源代码可以发现,默认会初始化类

  

  上述方法调用了forName0的native方法:该方法对于是否初始化该类的参数 initialize 设置为true,并且传入了调用者(caller)的类加载器。也可以使用forName的重载方法设置initialize为false。

  而使用第四种方式,loadClass方法源代码如下

  

  这里的resolve参数代表“解析”,即类加载过程中第二步“连接”中的第三部分“解析”,默认情况不解析,也可以使用loadClass的重载方法将resolve设置为true。也就是说loadClass方法不会初始化该类。

二、从Class对象中获取信息

  先来整理一下Class对象中通常获取的类信息:

    Constructor<T> 这里的反省T代表构造器创建的对象类型。

    Method

    Field

    <A extends Annotation> A ,由于使用@interface自定义注解时,都默认实现了Annotation接口,所以这里使用泛型A代表使用的

    Class[] 内部类

    Interfaces 该Class实现的全部接口

    Superclass

    Package 包

    Modifiers 该类所有的修饰符

    Name、SimpleName

    TypeVariable<Class<T>>[] ,由getTypeParameters方法返回,该数组代表类的定义中包含的泛型类型声明,如果如果泛型声明的一般签名不符合Java虚拟机规范中指定的格式,则抛出GenericSignatureFormatError错误。

  对于类的成员,又分为getEnclosing*、getDeclared*、getDeclaringClass、get*

    它们的区别为:getEnclosing*返回一个Class、Method、Constructor对象,当前类定义在该Class、Method、Constructor中。

           getDeclaringClass,返回一个类,当前类定义在这个类中作为成员(内部类或接口)。

           getDeclared*,返回当前类中定义的*,与访问修饰符所限定的权限无关。

           get*返回public的*。

  上述信息都可以通过Class对象的getXXX方法来获得,具体方法的使用可以查阅文档。

  除了getXXX方法,Class对象还提供了isXXX方法来帮助判断。

三、java8新增的方法参数反射

  java8在java.lang.reflect包下新增了一个Executable抽象基类,该对象代表可执行的类成员,该类派生了Constructor、Method两个字类。

  Executable类提供了大量方法来获取修饰该方法或构造器的注解信息,还提供了isVarArgs()方法来判断该方法或构造器是否包含数量可变的形参,该类还提供了下面两个方法来获取该方法的参数个数和形参名

  int getParameterCount();

  Parameter[] getParameters。

  其中Parameter类也是java8新增的类。通过Parameter类可以获取方法参数上面的信息,包括形参名、形参类型、泛型信息、注解信息等等。

  由于javac在编译java文件时会忽略掉形参名,所以若想利用反射获取形参名,需要在编译时加入-parameters 参数,即可在编译时保留形参名信息。

  获得Class的信息是在代码中动态操作Class的基础,下一节学习如何利用反射来动态操作代码。

 

posted @ 2017-10-31 10:52  The_shy  阅读(339)  评论(0编辑  收藏  举报