Java 反射(Class class相关)

>Class类:反射的根源

>1.Object class,是所有的Java classes的继承根源,

其内声明了数个应该在所有Java class中被改写methods:hashCode()、equals()、clone()、toString()、getClass()等。

其中getClass()返回了一个 Class object

>2.小插曲:为什么重写hashCode()和重写eauqls()要同时进行?

>3.Class class

  • Class class十分特殊。它和一般classes一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(8个)
  • (boolean, byte, char, short, int, long, float, double)以及关键词void
  • 当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class object。如果想借由“修改Java标准库源码”来观察Class object的实际生成时机(例如在Class的constructor内添加一个println())不能够!因为Class并没有public constructor
  • 换句话说,不能new!Class是通过Java虚拟机通过内部机制new出来实例,并且去执行的
  • Class是Reflection的起源。针对任何想要探勘的class,唯有先为它产生一个Class object,接下来才能经由后者唤起数十多个的Reflection APIs

>4.Class 对象取得途径:

Java允许多种方式为一个class生成对应的Class object,不管一个Java类生成多少个对象,这些对象所对应的Class对象只有唯一的一个。

  • Java 反射(Class class相关)
  • Java 反射(Class class相关)

注意:

  • 调用Object class 对应的Class对象的getsuperclass()会返回null(再往上,null调用任意方法都会抛空指针异常)
  • 最后的方式,对于原生的8种类型,使用.class语法,包装类型,使用.TYPE语法

>5.运行时生成instances

欲生成对象实体,在Reflection 动态机制中有两种作法,一个针对“无自变量ctor”,一个针对“带参数ctor”。如果欲调用的是“带参数ctor“就比较麻烦些,不再调用Class的newInstance(),而是调用Constructor 的newInstance()。首先准备一个Class[]做为ctor的参数类型(本例指定为一个double和一个int),然后以此为自变量调用getConstructor(),获得一个专属ctor。接下来再准备一个Object[] 做为ctor实参值(本例指定3.14159和125),调用上述专属ctor的newInstance()。

不含参数构造(省略了构造步骤):

Java 反射(Class class相关)

含参数构造(先获取相应的构造器,再用构造来生成对象,这种方式是通用的):

Java 反射(Class class相关)

>6.运行时调用methods

这个动作和上述调用“带参数之ctor”相当类似。首先准备一个Class[]做为参数类型(本例指定其中一个是String,另一个是Hashtable),然后以此为自变量调用getMethod(),获得特定的Method object。接下来准备一个Object[]放置自变量,然后调用上述所得之特定Method object的invoke()。
为什么获得Method object时不需指定回返类型?因为方法重载不包含返回值,只包含名字和返回值构成方法签名,来唯一标识一个方法。

Java 反射(Class class相关)

>7.运行时变更fields内容

首先调用ClassgetField()并指定field名称。获得特定的Field object之后便可直接调用Fieldget()set()

Java 反射(Class class相关)

最后,关于一些反射方法调用时,我们会发现传入了某个对象的引用,这是因为一个类可能生成多个不同的实例,当调用成员或者成员方法时,可能会得到不同的结果,所以我们必须要指定获取哪一个对象里的成员或者成员方法的执行。