(1)RTTI(Run-Time Type Identification,通过运行时类型识别)
RTTI的含义就是在运行时识别一个对象的类型,并可以获知该类的所有信息,包括接口,父类,方法,静态成员等等。其对应的类是Class对象,每个java里面的类都对应一个Class对象(在编写并且编译后),这个对象被保存在这个类的同名的 . class文件里。
为了实现RTTI需要JVM的类加载器来将目标类所对应的class对象加载至内存中,然后再获取该class对象的引用,通过该引用便可以获知目标类的所有信息,也即实现了RTTI。
获取class对象引用的主要有Class.forName(String str) 和 .class两种,但当使用第一种方式来创建引用时,类加载器会自动地初始化该Class对象。而第二种方式中,初始化被延迟到了在程序中对该类的静态方法或者非常数静态域进行首次引用的时候。
因此,只要你想在程序运行时使用类型信息,即RTTI,就必须先获得对恰当的Class对象的引用,Class.forName(String str)就是实现此功能的捷径,因为你不需要为了获的Class引用而持有该类型的对象。但另外一方面,如果你已拥有了一个感兴趣的对象时,那就可以通过调用该对象的getClass()方法来获取它的引用了,这个方法继承于Object类,它将返回表示该对象的实际类型的Class引用。
(2)反射是在程序运行时动态获取一个在编译时完全未知的对象
在上面说到,如果想要知道某个类型信息,RTTI可以告诉你,但是有一个限制:即这个类型在编译时必须已知。这样才能使用RTTI来识别它,并利用这些信息做一些有用的事。换句话说,在编译时,编译器必须知道所有要通过RTTI来处理的类(包括类名)。
如果,在磁盘上或者网络中的一段字符串,被告知代表一个类,但是编译器在编译代码的时候,并不知道,怎么才能使用这个类呢?这时候就需要使用反射。
通过反射与未知类型的对象打交道时,JVM会简单地检查这个对象,看它属于哪个特定的类(与RTTI一样)。然后,在做其它事情之前,必须加载那个类的 Class 对象。因此,那个类的.class 文件对于 JVM 来说必须是可获取的,要么在本地机器上,要么可以通过网络取得。
所以RTTI和反射之间真正的区别在于:对RTTI来说,编译器在编译时代开和检查.class文件,而对于反射机制来说,.class文件在编译时是不可获得的,即在运行时打开和检查.class文件。
之后便可以通过Class的getMethods()和getConstructors()方法分别获得Method对象的数组和Constructor对象的数组。这样便能够创建一个在编译时完全位置的对象。